On 10/22/20 2:06 PM, Anton Baskanov wrote:
Signed-off-by: Anton Baskanov baskanov@gmail.com
dlls/amstream/multimedia.c | 4 ++ dlls/amstream/tests/amstream.c | 84 ++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+)
diff --git a/dlls/amstream/multimedia.c b/dlls/amstream/multimedia.c index 82ef4822344..967baacb747 100644 --- a/dlls/amstream/multimedia.c +++ b/dlls/amstream/multimedia.c @@ -156,7 +156,11 @@ static HRESULT WINAPI multimedia_stream_SetState(IAMMultiMediaStream *iface, STR { hr = IMediaControl_Run(This->media_control); if (SUCCEEDED(hr))
{
FILTER_STATE state;
IMediaControl_GetState(This->media_control, INFINITE, (OAFilterState *)&state); hr = S_OK;
} else if (new_state == STREAMSTATE_STOP) hr = IMediaControl_Stop(This->media_control);}
diff --git a/dlls/amstream/tests/amstream.c b/dlls/amstream/tests/amstream.c index b436840e407..cb2b3dd76db 100644 --- a/dlls/amstream/tests/amstream.c +++ b/dlls/amstream/tests/amstream.c @@ -924,11 +924,13 @@ struct testfilter LONGLONG current_position; LONGLONG stop_position; const AM_MEDIA_TYPE *preferred_mt;
- CONDITION_VARIABLE wait_state_cv; HRESULT get_duration_hr; HRESULT get_stop_position_hr; HRESULT set_positions_hr; HRESULT init_stream_hr; HRESULT cleanup_stream_hr;
- HRESULT wait_state_hr;
};
static inline struct testfilter *impl_from_BaseFilter(struct strmbase_filter *iface) @@ -971,12 +973,37 @@ static HRESULT testfilter_cleanup_stream(struct strmbase_filter *iface) return filter->cleanup_stream_hr; }
+static HRESULT testfilter_wait_state(struct strmbase_filter *iface, DWORD timeout) +{
- struct testfilter *filter = impl_from_BaseFilter(iface);
- DWORD start_time = GetTickCount();
- DWORD elapsed = 0;
- HRESULT hr;
- EnterCriticalSection(&filter->filter.csFilter);
strmbase actually already grabs this.
- while (filter->wait_state_hr == VFW_S_STATE_INTERMEDIATE && elapsed < timeout)
- {
DWORD sleep_time = timeout - elapsed;
if (!SleepConditionVariableCS(&filter->wait_state_cv, &filter->filter.csFilter, sleep_time))
break;
elapsed = GetTickCount() - start_time;
- }
This is fine, though it'd also be fine, and perhaps a little simpler, to use an event.
(I know I may sound inconsistent. I do think that the usage patterns in prior patches are ideal for condition variables, where the condition needs to be rechecked *anyway*, and there may be multiple threads trying to use the same resource. The fact that condition variables are "fast" in Wine, at least on some platforms, is also a benefit for implementation code. Here the usage pattern is a little different, i.e. much more linear and controlled, so using an event gets a little easier, and of course speed doesn't matter as much.)
- hr = filter->wait_state_hr;
- LeaveCriticalSection(&filter->filter.csFilter);
- return hr;
+}
static const struct strmbase_filter_ops testfilter_ops = { .filter_get_pin = testfilter_get_pin, .filter_destroy = testfilter_destroy, .filter_init_stream = testfilter_init_stream, .filter_cleanup_stream = testfilter_cleanup_stream,
- .filter_wait_state = testfilter_wait_state,
};
static inline struct testfilter *impl_from_base_pin(struct strmbase_pin *iface) @@ -1060,6 +1087,7 @@ static void testfilter_init(struct testfilter *filter) strmbase_filter_init(&filter->filter, NULL, &clsid, &testfilter_ops); strmbase_source_init(&filter->source, &filter->filter, L"", &testsource_ops); filter->stop_position = 0x8000000000000000ULL;
- InitializeConditionVariable(&filter->wait_state_cv);
}
static inline struct testfilter *impl_from_IMediaSeeking(IMediaSeeking *iface) @@ -2319,11 +2347,25 @@ static void test_initialize(void) IUnknown_Release(graph_inner_unk); }
+static IAMMultiMediaStream *mmstream_mmstream; +static STREAM_STATE mmstream_state;
+static DWORD CALLBACK mmstream_set_state(void *param) +{
- HRESULT hr;
- hr = IAMMultiMediaStream_SetState(mmstream_mmstream, mmstream_state);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- return 0;
+}
static void test_set_state(void) { IAMMultiMediaStream *mmstream = create_ammultimediastream(); struct testfilter source; IGraphBuilder *graph;
- HANDLE thread; HRESULT hr; ULONG ref;
@@ -2353,6 +2395,41 @@ static void test_set_state(void) hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP); ok(hr == S_OK, "Got hr %#x.\n", hr);
- source.wait_state_hr = E_FAIL;
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- source.wait_state_hr = S_OK;
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- source.wait_state_hr = VFW_S_STATE_INTERMEDIATE;
- mmstream_mmstream = mmstream;
- mmstream_state = STREAMSTATE_RUN;
- thread = CreateThread(NULL, 0, mmstream_set_state, NULL, 0, NULL);
- ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "SetState returned prematurely.\n");
- EnterCriticalSection(&source.filter.csFilter);
- source.wait_state_hr = S_OK;
- WakeAllConditionVariable(&source.wait_state_cv);
- LeaveCriticalSection(&source.filter.csFilter);
- ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
- CloseHandle(thread);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- source.init_stream_hr = E_FAIL;
- source.wait_state_hr = VFW_S_STATE_INTERMEDIATE;
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
- ok(hr == E_FAIL, "Got hr %#x.\n", hr);
- source.init_stream_hr = S_OK;
- source.wait_state_hr = S_OK;
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN); ok(hr == S_OK, "Got hr %#x.\n", hr); source.cleanup_stream_hr = E_FAIL;
@@ -2369,6 +2446,13 @@ static void test_set_state(void) ok(hr == S_FALSE, "Got hr %#x.\n", hr); source.cleanup_stream_hr = S_OK;
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- source.wait_state_hr = VFW_S_STATE_INTERMEDIATE;
- hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
- ok(hr == S_OK, "Got hr %#x.\n", hr);
- source.wait_state_hr = S_OK;
- ref = IAMMultiMediaStream_Release(mmstream); ok(!ref, "Got outstanding refcount %d.\n", ref); ref = IGraphBuilder_Release(graph);