Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/filtergraph.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-)
diff --git a/dlls/quartz/tests/filtergraph.c b/dlls/quartz/tests/filtergraph.c index 0c627aaeafb..bd6562b0ed5 100644 --- a/dlls/quartz/tests/filtergraph.c +++ b/dlls/quartz/tests/filtergraph.c @@ -1166,14 +1166,15 @@ struct testfilter IFilterGraph *graph; WCHAR *name; IReferenceClock *clock; - FILTER_STATE state; - REFERENCE_TIME start_time;
IEnumPins IEnumPins_iface; struct testpin *pins; unsigned int pin_count, enum_idx;
+ FILTER_STATE state; + REFERENCE_TIME start_time; HRESULT state_hr, GetState_hr, seek_hr; + FILTER_STATE expect_stop_prev, expect_run_prev;
IAMFilterMiscFlags IAMFilterMiscFlags_iface; ULONG misc_flags; @@ -1358,6 +1359,10 @@ static HRESULT WINAPI testfilter_Stop(IBaseFilter *iface) struct testfilter *filter = impl_from_IBaseFilter(iface); if (winetest_debug > 1) trace("%p->Stop()\n", filter);
+ todo_wine_if (filter->expect_stop_prev == State_Running) + ok(filter->state == filter->expect_stop_prev, "Expected previous state %#x, got %#x.\n", + filter->expect_stop_prev, filter->state); + check_state_transition(filter, State_Stopped);
filter->state = State_Stopped; @@ -1380,6 +1385,9 @@ static HRESULT WINAPI testfilter_Run(IBaseFilter *iface, REFERENCE_TIME start) struct testfilter *filter = impl_from_IBaseFilter(iface); if (winetest_debug > 1) trace("%p->Run(%s)\n", filter, wine_dbgstr_longlong(start));
+ ok(filter->state == filter->expect_run_prev, "Expected previous state %#x, got %#x.\n", + filter->expect_run_prev, filter->state); + check_state_transition(filter, State_Running);
filter->state = State_Running; @@ -1831,7 +1839,9 @@ static void testfilter_init(struct testfilter *filter, struct testpin *pins, int filter->pin_count = pin_count; for (i = 0; i < pin_count; i++) pins[i].filter = &filter->IBaseFilter_iface; + filter->state = State_Stopped; + filter->expect_stop_prev = filter->expect_run_prev = State_Paused; }
static HRESULT WINAPI testfilter_cf_QueryInterface(IClassFactory *iface, REFIID iid, void **out) @@ -3383,6 +3393,7 @@ static void test_filter_state(void) ok(hr == S_OK, "Got hr %#x.\n", hr); check_filter_state(graph, State_Stopped);
+ source.expect_run_prev = sink.expect_run_prev = State_Stopped; hr = IReferenceClock_GetTime(clock, &start_time); ok(SUCCEEDED(hr), "Got hr %#x.\n", hr); hr = IMediaFilter_Run(filter, 0); @@ -3400,6 +3411,7 @@ static void test_filter_state(void) ok(hr == S_OK, "Got hr %#x.\n", hr); check_filter_state(graph, State_Paused);
+ source.expect_run_prev = sink.expect_run_prev = State_Paused; hr = IMediaFilter_Run(filter, 0); ok(hr == S_OK, "Got hr %#x.\n", hr); check_filter_state(graph, State_Running); @@ -3587,6 +3599,7 @@ todo_wine
/* This logic doesn't apply when using IMediaFilter methods directly. */
+ source.expect_run_prev = sink.expect_run_prev = State_Stopped; sink.state_hr = S_FALSE; sink.GetState_hr = VFW_S_STATE_INTERMEDIATE; hr = IMediaFilter_Run(filter, 0); @@ -3610,6 +3623,8 @@ todo_wine ok(sink.state == State_Stopped, "Got state %u.\n", sink.state); ok(source.state == State_Stopped, "Got state %u.\n", source.state);
+ source.expect_run_prev = sink.expect_run_prev = State_Paused; + /* Test VFW_S_CANT_CUE. */
sink.GetState_hr = VFW_S_CANT_CUE; @@ -3658,7 +3673,7 @@ todo_wine
/* Destroying the graph while it's running stops all filters. */
- hr = IMediaFilter_Run(filter, 0); + hr = IMediaControl_Run(control); ok(hr == S_OK, "Got hr %#x.\n", hr); check_filter_state(graph, State_Running); todo_wine @@ -3667,6 +3682,7 @@ todo_wine ok(sink.start_time == source.start_time, "Expected time %s, got %s.\n", wine_dbgstr_longlong(source.start_time), wine_dbgstr_longlong(sink.start_time));
+ source.expect_stop_prev = sink.expect_stop_prev = State_Running; IMediaFilter_Release(filter); IMediaControl_Release(control); ref = IFilterGraph2_Release(graph);
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/Makefile.in | 2 +- dlls/quartz/tests/dsoundrender.c | 118 +++++++++++++++++++++++++++++++ 2 files changed, 119 insertions(+), 1 deletion(-)
diff --git a/dlls/quartz/tests/Makefile.in b/dlls/quartz/tests/Makefile.in index 7652baf274e..b4a372d4d3e 100644 --- a/dlls/quartz/tests/Makefile.in +++ b/dlls/quartz/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = quartz.dll -IMPORTS = strmbase advapi32 d3d9 msdmo msvfw32 ole32 oleaut32 user32 uuid +IMPORTS = strmbase advapi32 d3d9 dsound msdmo msvfw32 ole32 oleaut32 user32 uuid
C_SRCS = \ acmwrapper.c \ diff --git a/dlls/quartz/tests/dsoundrender.c b/dlls/quartz/tests/dsoundrender.c index ecff4b7c882..3add14d0437 100644 --- a/dlls/quartz/tests/dsoundrender.c +++ b/dlls/quartz/tests/dsoundrender.c @@ -24,6 +24,7 @@ #include "initguid.h" #include "dsound.h" #include "amaudio.h" +#include "mmreg.h" #include "wine/test.h"
static const WCHAR sink_id[] = L"Audio Input pin (rendered)"; @@ -685,6 +686,122 @@ static void test_unconnected_filter_state(void) ok(!ref, "Got outstanding refcount %d.\n", ref); }
+static HRESULT does_dsound_support_format(WAVEFORMATEX *format) +{ + const DSBUFFERDESC desc = + { + .dwSize = sizeof(DSBUFFERDESC), + .dwBufferBytes = format->nAvgBytesPerSec, + .lpwfxFormat = format, + }; + IDirectSoundBuffer *buffer; + IDirectSound *dsound; + HRESULT hr; + + hr = DirectSoundCreate(NULL, &dsound, NULL); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IDirectSound_CreateSoundBuffer(dsound, &desc, &buffer, NULL); + if (hr == S_OK) + IDirectSoundBuffer_Release(buffer); + IDirectSound_Release(dsound); + + return hr == S_OK ? S_OK : S_FALSE; +} + +static void test_media_types(void) +{ + IBaseFilter *filter = create_dsound_render(); + AM_MEDIA_TYPE *mt, req_mt = {{0}}; + IEnumMediaTypes *enummt; + WAVEFORMATEX wfx = {0}; + HRESULT hr, expect_hr; + unsigned int i, j; + WORD channels; + ULONG ref; + IPin *pin; + + static const DWORD sample_rates[] = {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 96000}; + + static const struct + { + WORD tag; + WORD depth; + } formats[] = + { + {WAVE_FORMAT_PCM, 8}, + {WAVE_FORMAT_PCM, 16}, + {WAVE_FORMAT_PCM, 24}, + {WAVE_FORMAT_PCM, 32}, + {WAVE_FORMAT_IEEE_FLOAT, 32}, + {WAVE_FORMAT_IEEE_FLOAT, 64}, + }; + + IBaseFilter_FindPin(filter, sink_id, &pin); + + hr = IPin_EnumMediaTypes(pin, &enummt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IEnumMediaTypes_Next(enummt, 1, &mt, NULL); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + if (hr == S_OK) + { + ok(IsEqualGUID(&mt->majortype, &MEDIATYPE_Audio), "Got major type %s.\n", wine_dbgstr_guid(&mt->majortype)); + ok(IsEqualGUID(&mt->subtype, &GUID_NULL), "Got subtype %s.\n", wine_dbgstr_guid(&mt->subtype)); + ok(mt->bFixedSizeSamples == TRUE, "Got fixed size %d.\n", mt->bFixedSizeSamples); + ok(!mt->bTemporalCompression, "Got temporal compression %d.\n", mt->bTemporalCompression); + ok(mt->lSampleSize == 1, "Got sample size %u.\n", mt->lSampleSize); + ok(IsEqualGUID(&mt->formattype, &GUID_NULL), "Got format type %s.\n", wine_dbgstr_guid(&mt->formattype)); + ok(!mt->pUnk, "Got pUnk %p.\n", mt->pUnk); + ok(!mt->cbFormat, "Got format size %u.\n", mt->cbFormat); + ok(!mt->pbFormat, "Got unexpected format block.\n"); + + hr = IPin_QueryAccept(pin, mt); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + + CoTaskMemFree(mt); + } + + hr = IEnumMediaTypes_Next(enummt, 1, &mt, NULL); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + + req_mt.majortype = MEDIATYPE_Audio; + req_mt.formattype = FORMAT_WaveFormatEx; + req_mt.cbFormat = sizeof(WAVEFORMATEX); + req_mt.pbFormat = (BYTE *)&wfx; + + IEnumMediaTypes_Release(enummt); + + for (channels = 1; channels <= 2; ++channels) + { + wfx.nChannels = channels; + + for (i = 0; i < ARRAY_SIZE(formats); ++i) + { + wfx.wFormatTag = formats[i].tag; + wfx.wBitsPerSample = formats[i].depth; + wfx.nBlockAlign = wfx.nChannels * wfx.wBitsPerSample / 8; + for (j = 0; j < ARRAY_SIZE(sample_rates); ++j) + { + wfx.nSamplesPerSec = sample_rates[j]; + wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; + + expect_hr = does_dsound_support_format(&wfx); + + hr = IPin_QueryAccept(pin, &req_mt); + todo_wine_if (expect_hr == S_OK) + ok(hr == expect_hr, "Expected hr %#x, got %#x, for %d channels, %d-bit %s, %d Hz.\n", + expect_hr, hr, channels, formats[i].depth, + formats[i].tag == WAVE_FORMAT_PCM ? "integer" : "float", sample_rates[j]); + } + } + } + + IPin_Release(pin); + ref = IBaseFilter_Release(filter); + ok(!ref, "Got outstanding refcount %d.\n", ref); +} + START_TEST(dsoundrender) { IBaseFilter *filter; @@ -712,6 +829,7 @@ START_TEST(dsoundrender) test_basic_audio(); test_enum_media_types(); test_unconnected_filter_state(); + test_media_types(); test_basefilter();
CoUninitialize();
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/dsoundrender.c | 3 --- dlls/quartz/tests/dsoundrender.c | 7 +++---- 2 files changed, 3 insertions(+), 7 deletions(-)
diff --git a/dlls/quartz/dsoundrender.c b/dlls/quartz/dsoundrender.c index 8e6379da8ce..225c1e07b96 100644 --- a/dlls/quartz/dsoundrender.c +++ b/dlls/quartz/dsoundrender.c @@ -384,9 +384,6 @@ static HRESULT WINAPI DSoundRender_CheckMediaType(struct strmbase_renderer *ifac if (!IsEqualIID(&pmt->majortype, &MEDIATYPE_Audio)) return S_FALSE;
- if (!IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_PCM)) - return S_FALSE; - return S_OK; }
diff --git a/dlls/quartz/tests/dsoundrender.c b/dlls/quartz/tests/dsoundrender.c index 3add14d0437..0b45d712dc0 100644 --- a/dlls/quartz/tests/dsoundrender.c +++ b/dlls/quartz/tests/dsoundrender.c @@ -789,10 +789,9 @@ static void test_media_types(void) expect_hr = does_dsound_support_format(&wfx);
hr = IPin_QueryAccept(pin, &req_mt); - todo_wine_if (expect_hr == S_OK) - ok(hr == expect_hr, "Expected hr %#x, got %#x, for %d channels, %d-bit %s, %d Hz.\n", - expect_hr, hr, channels, formats[i].depth, - formats[i].tag == WAVE_FORMAT_PCM ? "integer" : "float", sample_rates[j]); + ok(hr == expect_hr, "Expected hr %#x, got %#x, for %d channels, %d-bit %s, %d Hz.\n", + expect_hr, hr, channels, formats[i].depth, + formats[i].tag == WAVE_FORMAT_PCM ? "integer" : "float", sample_rates[j]); } } }
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/dsoundrender.c | 138 +++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+)
diff --git a/dlls/quartz/tests/dsoundrender.c b/dlls/quartz/tests/dsoundrender.c index 0b45d712dc0..22d5bf62824 100644 --- a/dlls/quartz/tests/dsoundrender.c +++ b/dlls/quartz/tests/dsoundrender.c @@ -25,6 +25,7 @@ #include "dsound.h" #include "amaudio.h" #include "mmreg.h" +#include "wine/strmbase.h" #include "wine/test.h"
static const WCHAR sink_id[] = L"Audio Input pin (rendered)"; @@ -38,6 +39,12 @@ static IBaseFilter *create_dsound_render(void) return filter; }
+static inline BOOL compare_media_types(const AM_MEDIA_TYPE *a, const AM_MEDIA_TYPE *b) +{ + return !memcmp(a, b, offsetof(AM_MEDIA_TYPE, pbFormat)) + && !memcmp(a->pbFormat, b->pbFormat, a->cbFormat); +} + static ULONG get_refcount(void *iface) { IUnknown *unknown = iface; @@ -573,6 +580,136 @@ static void test_enum_media_types(void) ok(!ref, "Got outstanding refcount %d.\n", ref); }
+struct testfilter +{ + struct strmbase_filter filter; + struct strmbase_source source; +}; + +static inline struct testfilter *impl_from_strmbase_filter(struct strmbase_filter *iface) +{ + return CONTAINING_RECORD(iface, struct testfilter, filter); +} + +static struct strmbase_pin *testfilter_get_pin(struct strmbase_filter *iface, unsigned int index) +{ + struct testfilter *filter = impl_from_strmbase_filter(iface); + if (!index) + return &filter->source.pin; + return NULL; +} + +static void testfilter_destroy(struct strmbase_filter *iface) +{ + struct testfilter *filter = impl_from_strmbase_filter(iface); + strmbase_source_cleanup(&filter->source); + strmbase_filter_cleanup(&filter->filter); +} + +static const struct strmbase_filter_ops testfilter_ops = +{ + .filter_get_pin = testfilter_get_pin, + .filter_destroy = testfilter_destroy, +}; + +static HRESULT WINAPI testsource_DecideAllocator(struct strmbase_source *iface, + IMemInputPin *peer, IMemAllocator **allocator) +{ + return S_OK; +} + +static const struct strmbase_source_ops testsource_ops = +{ + .pfnAttemptConnection = BaseOutputPinImpl_AttemptConnection, + .pfnDecideAllocator = testsource_DecideAllocator, +}; + +static void testfilter_init(struct testfilter *filter) +{ + static const GUID clsid = {0xabacab}; + strmbase_filter_init(&filter->filter, NULL, &clsid, &testfilter_ops); + strmbase_source_init(&filter->source, &filter->filter, L"", &testsource_ops); +} + +static void test_connect_pin(void) +{ + WAVEFORMATEX wfx = + { + .wFormatTag = WAVE_FORMAT_PCM, + .nChannels = 2, + .nSamplesPerSec = 44100, + .nAvgBytesPerSec = 44100 * 4, + .nBlockAlign = 4, + .wBitsPerSample = 16, + }; + AM_MEDIA_TYPE req_mt = + { + .majortype = MEDIATYPE_Audio, + .subtype = MEDIASUBTYPE_PCM, + .formattype = FORMAT_WaveFormatEx, + .cbFormat = sizeof(wfx), + .pbFormat = (BYTE *)&wfx, + }; + IBaseFilter *filter = create_dsound_render(); + struct testfilter source; + IFilterGraph2 *graph; + AM_MEDIA_TYPE mt; + IPin *pin, *peer; + HRESULT hr; + ULONG ref; + + testfilter_init(&source); + + CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterGraph2, (void **)&graph); + IFilterGraph2_AddFilter(graph, &source.filter.IBaseFilter_iface, L"source"); + IFilterGraph2_AddFilter(graph, filter, L"sink"); + + IBaseFilter_FindPin(filter, sink_id, &pin); + + peer = (IPin *)0xdeadbeef; + hr = IPin_ConnectedTo(pin, &peer); + ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr); + ok(!peer, "Got peer %p.\n", peer); + + hr = IPin_ConnectionMediaType(pin, &mt); + ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr); + + hr = IFilterGraph2_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &req_mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IPin_ConnectedTo(pin, &peer); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(peer == &source.source.pin.IPin_iface, "Got peer %p.\n", peer); + IPin_Release(peer); + + hr = IPin_ConnectionMediaType(pin, &mt); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(compare_media_types(&mt, &req_mt), "Media types didn't match.\n"); + + hr = IFilterGraph2_Disconnect(graph, pin); + ok(hr == S_OK, "Got hr %#x.\n", hr); + hr = IFilterGraph2_Disconnect(graph, pin); + ok(hr == S_FALSE, "Got hr %#x.\n", hr); + ok(source.source.pin.peer == pin, "Got peer %p.\n", source.source.pin.peer); + IFilterGraph2_Disconnect(graph, &source.source.pin.IPin_iface); + + peer = (IPin *)0xdeadbeef; + hr = IPin_ConnectedTo(pin, &peer); + ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr); + ok(!peer, "Got peer %p.\n", peer); + + hr = IPin_ConnectionMediaType(pin, &mt); + ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr); + + IPin_Release(pin); + ref = IFilterGraph2_Release(graph); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ref = IBaseFilter_Release(filter); + ok(!ref, "Got outstanding refcount %d.\n", ref); + ref = IBaseFilter_Release(&source.filter.IBaseFilter_iface); + ok(!ref, "Got outstanding refcount %d.\n", ref); +} + static void test_pin(IPin *pin) { IMemInputPin *mpin = NULL; @@ -829,6 +966,7 @@ START_TEST(dsoundrender) test_enum_media_types(); test_unconnected_filter_state(); test_media_types(); + test_connect_pin(); test_basefilter();
CoUninitialize();
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/quartz/tests/dsoundrender.c | 49 ++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+)
diff --git a/dlls/quartz/tests/dsoundrender.c b/dlls/quartz/tests/dsoundrender.c index 22d5bf62824..d5c18d389a4 100644 --- a/dlls/quartz/tests/dsoundrender.c +++ b/dlls/quartz/tests/dsoundrender.c @@ -631,6 +631,49 @@ static void testfilter_init(struct testfilter *filter) strmbase_source_init(&filter->source, &filter->filter, L"", &testsource_ops); }
+static void test_allocator(IMemInputPin *input) +{ + IMemAllocator *req_allocator, *ret_allocator; + ALLOCATOR_PROPERTIES props; + HRESULT hr; + + hr = IMemInputPin_GetAllocatorRequirements(input, &props); + ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr); + + hr = IMemInputPin_GetAllocator(input, &ret_allocator); + todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr); + + if (hr == S_OK) + { + hr = IMemAllocator_GetProperties(ret_allocator, &props); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(!props.cBuffers, "Got %d buffers.\n", props.cBuffers); + ok(!props.cbBuffer, "Got size %d.\n", props.cbBuffer); + ok(!props.cbAlign, "Got alignment %d.\n", props.cbAlign); + ok(!props.cbPrefix, "Got prefix %d.\n", props.cbPrefix); + + hr = IMemInputPin_NotifyAllocator(input, ret_allocator, TRUE); + ok(hr == S_OK, "Got hr %#x.\n", hr); + IMemAllocator_Release(ret_allocator); + } + + hr = IMemInputPin_NotifyAllocator(input, NULL, TRUE); + ok(hr == E_POINTER, "Got hr %#x.\n", hr); + + CoCreateInstance(&CLSID_MemoryAllocator, NULL, CLSCTX_INPROC_SERVER, + &IID_IMemAllocator, (void **)&req_allocator); + + hr = IMemInputPin_NotifyAllocator(input, req_allocator, TRUE); + ok(hr == S_OK, "Got hr %#x.\n", hr); + + hr = IMemInputPin_GetAllocator(input, &ret_allocator); + ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(ret_allocator == req_allocator, "Allocators didn't match.\n"); + + IMemAllocator_Release(req_allocator); + IMemAllocator_Release(ret_allocator); +} + static void test_connect_pin(void) { WAVEFORMATEX wfx = @@ -653,6 +696,7 @@ static void test_connect_pin(void) IBaseFilter *filter = create_dsound_render(); struct testfilter source; IFilterGraph2 *graph; + IMemInputPin *input; AM_MEDIA_TYPE mt; IPin *pin, *peer; HRESULT hr; @@ -686,6 +730,10 @@ static void test_connect_pin(void) ok(hr == S_OK, "Got hr %#x.\n", hr); ok(compare_media_types(&mt, &req_mt), "Media types didn't match.\n");
+ IPin_QueryInterface(pin, &IID_IMemInputPin, (void **)&input); + + test_allocator(input); + hr = IFilterGraph2_Disconnect(graph, pin); ok(hr == S_OK, "Got hr %#x.\n", hr); hr = IFilterGraph2_Disconnect(graph, pin); @@ -701,6 +749,7 @@ static void test_connect_pin(void) hr = IPin_ConnectionMediaType(pin, &mt); ok(hr == VFW_E_NOT_CONNECTED, "Got hr %#x.\n", hr);
+ IMemInputPin_Release(input); IPin_Release(pin); ref = IFilterGraph2_Release(graph); ok(!ref, "Got outstanding refcount %d.\n", ref);