From 859809be485247d15ef63b4fcc97d5868020ebc4 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Sun, 6 Feb 2022 20:59:41 -0600 Subject: [PATCH] qcap/vfwcapture: Allow changing state while unconnected. Signed-off-by: Zebediah Figura Signed-off-by: Alexandre Julliard --- dlls/qcap/tests/videocapture.c | 53 ++++++++++++++++++++++++++++++++++ dlls/qcap/vfwcapture.c | 18 +++++++++++- 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/dlls/qcap/tests/videocapture.c b/dlls/qcap/tests/videocapture.c index c44070b0bd5..4e9dca7d837 100644 --- a/dlls/qcap/tests/videocapture.c +++ b/dlls/qcap/tests/videocapture.c @@ -296,6 +296,58 @@ static void test_misc_flags(IBaseFilter *filter) IAMFilterMiscFlags_Release(misc_flags); } +static void test_unconnected_filter_state(IBaseFilter *filter) +{ + FILTER_STATE state; + HRESULT hr; + + hr = IBaseFilter_GetState(filter, 0, &state); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(state == State_Stopped, "Got state %u.\n", state); + + hr = IBaseFilter_Pause(filter); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IBaseFilter_GetState(filter, 0, &state); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(state == State_Paused, "Got state %u.\n", state); + + hr = IBaseFilter_Run(filter, 0); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IBaseFilter_GetState(filter, 0, &state); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(state == State_Running, "Got state %u.\n", state); + + hr = IBaseFilter_Pause(filter); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IBaseFilter_GetState(filter, 0, &state); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(state == State_Paused, "Got state %u.\n", state); + + hr = IBaseFilter_Stop(filter); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IBaseFilter_GetState(filter, 0, &state); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(state == State_Stopped, "Got state %u.\n", state); + + hr = IBaseFilter_Run(filter, 0); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IBaseFilter_GetState(filter, 0, &state); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(state == State_Running, "Got state %u.\n", state); + + hr = IBaseFilter_Stop(filter); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IBaseFilter_GetState(filter, 0, &state); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(state == State_Stopped, "Got state %u.\n", state); +} + struct testfilter { struct strmbase_filter filter; @@ -615,6 +667,7 @@ START_TEST(videocapture) test_filter_interfaces(filter); test_pins(filter); test_misc_flags(filter); + test_unconnected_filter_state(filter); ref = IBaseFilter_Release(filter); ok(!ref, "Got outstanding refcount %d.\n", ref); diff --git a/dlls/qcap/vfwcapture.c b/dlls/qcap/vfwcapture.c index 6b82af9d155..7e6b0ee5afe 100644 --- a/dlls/qcap/vfwcapture.c +++ b/dlls/qcap/vfwcapture.c @@ -199,6 +199,9 @@ static HRESULT vfw_capture_init_stream(struct strmbase_filter *iface) struct vfw_capture *filter = impl_from_strmbase_filter(iface); HRESULT hr; + if (!filter->source.pin.peer) + return S_OK; + if (FAILED(hr = IMemAllocator_Commit(filter->source.pAllocator))) ERR("Failed to commit allocator, hr %#x.\n", hr); @@ -215,6 +218,9 @@ static HRESULT vfw_capture_start_stream(struct strmbase_filter *iface, REFERENCE { struct vfw_capture *filter = impl_from_strmbase_filter(iface); + if (!filter->source.pin.peer) + return S_OK; + EnterCriticalSection(&filter->state_cs); filter->state = State_Running; LeaveCriticalSection(&filter->state_cs); @@ -226,6 +232,9 @@ static HRESULT vfw_capture_stop_stream(struct strmbase_filter *iface) { struct vfw_capture *filter = impl_from_strmbase_filter(iface); + if (!filter->source.pin.peer) + return S_OK; + EnterCriticalSection(&filter->state_cs); filter->state = State_Paused; LeaveCriticalSection(&filter->state_cs); @@ -237,6 +246,9 @@ static HRESULT vfw_capture_cleanup_stream(struct strmbase_filter *iface) struct vfw_capture *filter = impl_from_strmbase_filter(iface); HRESULT hr; + if (!filter->source.pin.peer) + return S_OK; + EnterCriticalSection(&filter->state_cs); filter->state = State_Stopped; LeaveCriticalSection(&filter->state_cs); @@ -255,7 +267,11 @@ static HRESULT vfw_capture_cleanup_stream(struct strmbase_filter *iface) static HRESULT vfw_capture_wait_state(struct strmbase_filter *iface, DWORD timeout) { - return iface->state == State_Paused ? VFW_S_CANT_CUE : S_OK; + struct vfw_capture *filter = impl_from_strmbase_filter(iface); + + if (filter->source.pin.peer && filter->filter.state == State_Paused) + return VFW_S_CANT_CUE; + return S_OK; } static const struct strmbase_filter_ops filter_ops =