From: Zebediah Figura zfigura@codeweavers.com
--- dlls/qcap/audiorecord.c | 77 +++++++++++++++++++++++++++++++++++ dlls/qcap/tests/audiorecord.c | 1 + 2 files changed, 78 insertions(+)
diff --git a/dlls/qcap/audiorecord.c b/dlls/qcap/audiorecord.c index 6dcffb072fc..40fde996479 100644 --- a/dlls/qcap/audiorecord.c +++ b/dlls/qcap/audiorecord.c @@ -29,6 +29,7 @@ struct audio_record IPersistPropertyBag IPersistPropertyBag_iface;
struct strmbase_source source; + IAMStreamConfig IAMStreamConfig_iface; };
static struct audio_record *impl_from_strmbase_filter(struct strmbase_filter *filter) @@ -36,6 +37,19 @@ static struct audio_record *impl_from_strmbase_filter(struct strmbase_filter *fi return CONTAINING_RECORD(filter, struct audio_record, filter); }
+static HRESULT audio_record_source_query_interface(struct strmbase_pin *iface, REFIID iid, void **out) +{ + struct audio_record *filter = impl_from_strmbase_filter(iface->filter); + + if (IsEqualGUID(iid, &IID_IAMStreamConfig)) + *out = &filter->IAMStreamConfig_iface; + else + return E_NOINTERFACE; + + IUnknown_AddRef((IUnknown *)*out); + return S_OK; +} + static HRESULT WINAPI audio_record_source_DecideBufferSize(struct strmbase_source *iface, IMemAllocator *allocator, ALLOCATOR_PROPERTIES *props) { @@ -46,11 +60,73 @@ static HRESULT WINAPI audio_record_source_DecideBufferSize(struct strmbase_sourc
static const struct strmbase_source_ops source_ops = { + .base.pin_query_interface = audio_record_source_query_interface, .pfnAttemptConnection = BaseOutputPinImpl_AttemptConnection, .pfnDecideAllocator = BaseOutputPinImpl_DecideAllocator, .pfnDecideBufferSize = audio_record_source_DecideBufferSize, };
+static struct audio_record *impl_from_IAMStreamConfig(IAMStreamConfig *iface) +{ + return CONTAINING_RECORD(iface, struct audio_record, IAMStreamConfig_iface); +} + +static HRESULT WINAPI stream_config_QueryInterface(IAMStreamConfig *iface, REFIID iid, void **out) +{ + struct audio_record *filter = impl_from_IAMStreamConfig(iface); + return IPin_QueryInterface(&filter->source.pin.IPin_iface, iid, out); +} + +static ULONG WINAPI stream_config_AddRef(IAMStreamConfig *iface) +{ + struct audio_record *filter = impl_from_IAMStreamConfig(iface); + return IPin_AddRef(&filter->source.pin.IPin_iface); +} + +static ULONG WINAPI stream_config_Release(IAMStreamConfig *iface) +{ + struct audio_record *filter = impl_from_IAMStreamConfig(iface); + return IPin_Release(&filter->source.pin.IPin_iface); +} + +static HRESULT WINAPI stream_config_SetFormat(IAMStreamConfig *iface, AM_MEDIA_TYPE *mt) +{ + FIXME("iface %p, mt %p, stub!\n", iface, mt); + strmbase_dump_media_type(mt); + return E_NOTIMPL; +} + +static HRESULT WINAPI stream_config_GetFormat(IAMStreamConfig *iface, AM_MEDIA_TYPE **mt) +{ + FIXME("iface %p, mt %p, stub!\n", iface, mt); + return E_NOTIMPL; +} + +static HRESULT WINAPI stream_config_GetNumberOfCapabilities(IAMStreamConfig *iface, + int *count, int *size) +{ + FIXME("iface %p, count %p, size %p, stub!\n", iface, count, size); + return E_NOTIMPL; +} + +static HRESULT WINAPI stream_config_GetStreamCaps(IAMStreamConfig *iface, + int index, AM_MEDIA_TYPE **mt, BYTE *caps) +{ + FIXME("iface %p, index %d, mt %p, caps %p, stub!\n", iface, index, mt, caps); + return E_NOTIMPL; +} + +static const IAMStreamConfigVtbl stream_config_vtbl = +{ + stream_config_QueryInterface, + stream_config_AddRef, + stream_config_Release, + stream_config_SetFormat, + stream_config_GetFormat, + stream_config_GetNumberOfCapabilities, + stream_config_GetStreamCaps, +}; + static struct audio_record *impl_from_IPersistPropertyBag(IPersistPropertyBag *iface) { return CONTAINING_RECORD(iface, struct audio_record, IPersistPropertyBag_iface); @@ -178,6 +254,7 @@ HRESULT audio_record_create(IUnknown *outer, IUnknown **out) strmbase_filter_init(&object->filter, outer, &CLSID_AudioRecord, &filter_ops);
strmbase_source_init(&object->source, &object->filter, L"Capture", &source_ops); + object->IAMStreamConfig_iface.lpVtbl = &stream_config_vtbl;
TRACE("Created audio recorder %p.\n", object); *out = &object->filter.IUnknown_inner; diff --git a/dlls/qcap/tests/audiorecord.c b/dlls/qcap/tests/audiorecord.c index 64fc09c49fc..b851884ec3b 100644 --- a/dlls/qcap/tests/audiorecord.c +++ b/dlls/qcap/tests/audiorecord.c @@ -71,6 +71,7 @@ static void test_interfaces(IBaseFilter *filter) hr = IBaseFilter_FindPin(filter, L"Capture", &pin); ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ check_interface(pin, &IID_IAMStreamConfig, TRUE); todo_wine check_interface(pin, &IID_IKsPropertySet, TRUE); check_interface(pin, &IID_IPin, TRUE); todo_wine check_interface(pin, &IID_IQualityControl, TRUE);
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/qcap/tests/audiorecord.c | 250 ++++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+)
diff --git a/dlls/qcap/tests/audiorecord.c b/dlls/qcap/tests/audiorecord.c index b851884ec3b..89964100ab6 100644 --- a/dlls/qcap/tests/audiorecord.c +++ b/dlls/qcap/tests/audiorecord.c @@ -20,9 +20,38 @@ */
#define COBJMACROS +#include <stdbool.h> #include "dshow.h" +#include "mmreg.h" +#include "wine/strmbase.h" #include "wine/test.h"
+static 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 void init_pcm_mt(AM_MEDIA_TYPE *mt, WAVEFORMATEX *format, + WORD channels, DWORD sample_rate, WORD depth) +{ + memset(format, 0, sizeof(WAVEFORMATEX)); + format->wFormatTag = WAVE_FORMAT_PCM; + format->nChannels = channels; + format->nSamplesPerSec = sample_rate; + format->wBitsPerSample = depth; + format->nBlockAlign = channels * depth / 8; + format->nAvgBytesPerSec = format->nBlockAlign * format->nSamplesPerSec; + memset(mt, 0, sizeof(AM_MEDIA_TYPE)); + mt->majortype = MEDIATYPE_Audio; + mt->subtype = MEDIASUBTYPE_PCM; + mt->bFixedSizeSamples = TRUE; + mt->lSampleSize = format->nBlockAlign; + mt->formattype = FORMAT_WaveFormatEx; + mt->cbFormat = sizeof(WAVEFORMATEX); + mt->pbFormat = (BYTE *)format; +} + static ULONG get_refcount(void *iface) { IUnknown *unknown = iface; @@ -343,6 +372,224 @@ static void test_pin_info(IBaseFilter *filter) IPin_Release(pin); }
+static void test_media_types(IBaseFilter *filter) +{ + WAVEFORMATEX format, *pformat; + IEnumMediaTypes *enummt; + AM_MEDIA_TYPE mt, *pmt; + HRESULT hr; + IPin *pin; + + IBaseFilter_FindPin(filter, L"Capture", &pin); + + hr = IPin_EnumMediaTypes(pin, &enummt); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IEnumMediaTypes_Next(enummt, 1, &pmt, NULL); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + if (hr == S_OK) + { + pformat = (void *)pmt->pbFormat; + ok(pformat->nChannels == 2, "Got %u channels.\n", pformat->nChannels); + ok(pformat->wBitsPerSample == 16, "Got depth %u.\n", pformat->wBitsPerSample); + ok(pformat->nSamplesPerSec == 44100, "Got sample rate %lu.\n", pformat->nSamplesPerSec); + + do + { + pformat = (void *)pmt->pbFormat; + + ok(IsEqualGUID(&pmt->majortype, &MEDIATYPE_Audio), "Got major type %s.\n", + debugstr_guid(&pmt->majortype)); + ok(IsEqualGUID(&pmt->subtype, &MEDIASUBTYPE_PCM), "Got subtype %s\n", + debugstr_guid(&pmt->subtype)); + ok(pmt->bFixedSizeSamples == TRUE, "Got fixed size %d.\n", pmt->bFixedSizeSamples); + ok(!pmt->bTemporalCompression, "Got temporal compression %d.\n", pmt->bTemporalCompression); + ok(pmt->lSampleSize == pformat->nBlockAlign, "Got sample size %lu.\n", pmt->lSampleSize); + ok(IsEqualGUID(&pmt->formattype, &FORMAT_WaveFormatEx), "Got format type %s.\n", + debugstr_guid(&pmt->formattype)); + ok(!pmt->pUnk, "Got pUnk %p.\n", pmt->pUnk); + ok(pmt->cbFormat == sizeof(WAVEFORMATEX), "Got format size %lu.\n", pmt->cbFormat); + + ok(pformat->wFormatTag == WAVE_FORMAT_PCM, "Got format %#x.\n", pformat->wFormatTag); + ok(pformat->nChannels == 1 || pformat->nChannels == 2, "Got %u channels.\n", pformat->nChannels); + ok(pformat->wBitsPerSample == 8 || pformat->wBitsPerSample == 16, "Got depth %u.\n", pformat->wBitsPerSample); + ok(pformat->nBlockAlign == pformat->nChannels * pformat->wBitsPerSample / 8, + "Got block align %u.\n", pformat->nBlockAlign); + ok(pformat->nAvgBytesPerSec == pformat->nSamplesPerSec * pformat->nBlockAlign, + "Got %lu bytes per second.\n", pformat->nAvgBytesPerSec); + ok(!pformat->cbSize, "Got size %u.\n", pformat->cbSize); + + strmbase_dump_media_type(pmt); + + hr = IPin_QueryAccept(pin, pmt); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + CoTaskMemFree(pmt->pbFormat); + CoTaskMemFree(pmt); + + hr = IEnumMediaTypes_Next(enummt, 1, &pmt, NULL); + } while (hr == S_OK); + } + + ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + + init_pcm_mt(&mt, &format, 1, 44100, 8); + mt.subtype = MEDIASUBTYPE_RGB8; + mt.bFixedSizeSamples = FALSE; + mt.bTemporalCompression = TRUE; + mt.lSampleSize = 123; + format.nAvgBytesPerSec = 123; + hr = IPin_QueryAccept(pin, &mt); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + init_pcm_mt(&mt, &format, 1, 44100, 8); + mt.majortype = MEDIATYPE_Stream; + hr = IPin_QueryAccept(pin, &mt); + todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + mt.majortype = GUID_NULL; + hr = IPin_QueryAccept(pin, &mt); + todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + + init_pcm_mt(&mt, &format, 1, 44100, 8); + mt.formattype = FORMAT_None; + hr = IPin_QueryAccept(pin, &mt); + todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + mt.formattype = GUID_NULL; + hr = IPin_QueryAccept(pin, &mt); + todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + + init_pcm_mt(&mt, &format, 1, 44100, 8); + format.wFormatTag = 0xdead; + hr = IPin_QueryAccept(pin, &mt); + todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + + /* Validation of format members seems to vary across windows versions. */ + + IEnumMediaTypes_Release(enummt); + IPin_Release(pin); +} + +static void test_stream_config(IBaseFilter *filter) +{ + AUDIO_STREAM_CONFIG_CAPS caps; + IEnumMediaTypes *enummt; + IAMStreamConfig *config; + AM_MEDIA_TYPE *mt, *mt2; + int count, size, i; + IPin *source; + HRESULT hr; + + IBaseFilter_FindPin(filter, L"Capture", &source); + IPin_QueryInterface(source, &IID_IAMStreamConfig, (void **)&config); + + count = size = 0xdeadbeef; + hr = IAMStreamConfig_GetNumberOfCapabilities(config, &count, &size); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine ok(count && count != 0xdeadbeef, "Got count %d.\n", count); + todo_wine ok(size == sizeof(AUDIO_STREAM_CONFIG_CAPS), "Got size %d.\n", size); + + hr = IPin_EnumMediaTypes(source, &enummt); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + for (i = 0; i < count; ++i) + { + winetest_push_context("Caps %u", i); + + hr = IAMStreamConfig_GetStreamCaps(config, i, &mt, (BYTE *)&caps); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IEnumMediaTypes_Next(enummt, 1, &mt2, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(compare_media_types(mt, mt2), "Media types didn't match.\n"); + + ok(IsEqualGUID(&caps.guid, &MEDIATYPE_Audio), "Got GUID %s.\n", debugstr_guid(&caps.guid)); + ok(caps.MinimumChannels == 1, "Got minimum channels %lu.\n", caps.MinimumChannels); + ok(caps.MaximumChannels == 2, "Got maximum channels %lu.\n", caps.MaximumChannels); + ok(caps.ChannelsGranularity == 1, "Got channels granularity %lu.\n", caps.ChannelsGranularity); + ok(caps.MinimumBitsPerSample == 8, "Got minimum depth %lu.\n", caps.MinimumBitsPerSample); + ok(caps.MaximumBitsPerSample == 16, "Got maximum depth %lu.\n", caps.MaximumBitsPerSample); + ok(caps.BitsPerSampleGranularity == 8, "Got depth granularity %lu.\n", caps.BitsPerSampleGranularity); + ok(caps.MinimumSampleFrequency == 11025, "Got minimum rate %lu.\n", caps.MinimumSampleFrequency); + ok(caps.MaximumSampleFrequency == 44100, "Got maximum rate %lu.\n", caps.MaximumSampleFrequency); + ok(caps.SampleFrequencyGranularity == 11025, "Got rate granularity %lu.\n", caps.SampleFrequencyGranularity); + + DeleteMediaType(mt2); + DeleteMediaType(mt); + + winetest_pop_context(); + } + + hr = IAMStreamConfig_GetStreamCaps(config, count, &mt, (BYTE *)&caps); + todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + hr = IEnumMediaTypes_Next(enummt, 1, &mt2, NULL); + ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + + IEnumMediaTypes_Release(enummt); + + hr = IAMStreamConfig_GetFormat(config, &mt); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + if (hr == S_OK) + { + hr = IAMStreamConfig_GetStreamCaps(config, 0, &mt2, (BYTE *)&caps); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + if (hr == S_OK) + { + ok(compare_media_types(mt, mt2), "Media types didn't match.\n"); + DeleteMediaType(mt2); + } + + hr = IAMStreamConfig_SetFormat(config, NULL); + todo_wine ok(hr == E_POINTER, "Got hr %#lx.\n", hr); + + mt->majortype = MEDIATYPE_Video; + hr = IAMStreamConfig_SetFormat(config, mt); + todo_wine ok(hr == VFW_E_INVALIDMEDIATYPE, "Got hr %#lx.\n", hr); + + DeleteMediaType(mt); + } + + for (i = 0; i < count; ++i) + { + winetest_push_context("Caps %u", i); + + hr = IAMStreamConfig_GetStreamCaps(config, i, &mt, (BYTE *)&caps); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + if (hr == S_OK) + { + hr = IAMStreamConfig_SetFormat(config, mt); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IAMStreamConfig_GetFormat(config, &mt2); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(compare_media_types(mt, mt2), "Media types didn't match.\n"); + DeleteMediaType(mt2); + + DeleteMediaType(mt); + } + winetest_pop_context(); + } + + /* Unlike the WDM video capture filter, IEnumMediaTypes() still enumerates + * all media types. */ + IPin_EnumMediaTypes(source, &enummt); + for (i = 0; i < count; ++i) + { + hr = IAMStreamConfig_GetStreamCaps(config, i, &mt, (BYTE *)&caps); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IEnumMediaTypes_Next(enummt, 1, &mt2, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(compare_media_types(mt, mt2), "Media types didn't match.\n"); + + DeleteMediaType(mt2); + DeleteMediaType(mt); + } + IEnumMediaTypes_Release(enummt); + + IAMStreamConfig_Release(config); + IPin_Release(source); +} + START_TEST(audiorecord) { ICreateDevEnum *devenum; @@ -391,6 +638,9 @@ START_TEST(audiorecord) test_interfaces(filter); test_unconnected_filter_state(filter); test_pin_info(filter); + test_media_types(filter); + /* This calls SetFormat() and hence should be run last. */ + test_stream_config(filter);
ref = IBaseFilter_Release(filter); ok(!ref, "Got outstanding refcount %ld.\n", ref);
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/qcap/audiorecord.c | 69 +++++++++++++++++++++++++++++ dlls/qcap/tests/audiorecord.c | 82 +++++++++++++++++------------------ 2 files changed, 109 insertions(+), 42 deletions(-)
diff --git a/dlls/qcap/audiorecord.c b/dlls/qcap/audiorecord.c index 40fde996479..7107f22851b 100644 --- a/dlls/qcap/audiorecord.c +++ b/dlls/qcap/audiorecord.c @@ -50,6 +50,74 @@ static HRESULT audio_record_source_query_interface(struct strmbase_pin *iface, R return S_OK; }
+static const struct +{ + unsigned int rate; + unsigned int depth; + unsigned int channels; +} +audio_formats[] = +{ + {44100, 16, 2}, + {44100, 16, 1}, + {32000, 16, 2}, + {32000, 16, 1}, + {22050, 16, 2}, + {22050, 16, 1}, + {11025, 16, 2}, + {11025, 16, 1}, + { 8000, 16, 2}, + { 8000, 16, 1}, + {44100, 8, 2}, + {44100, 8, 1}, + {22050, 8, 2}, + {22050, 8, 1}, + {11025, 8, 2}, + {11025, 8, 1}, + { 8000, 8, 2}, + { 8000, 8, 1}, + {48000, 16, 2}, + {48000, 16, 1}, + {96000, 16, 2}, + {96000, 16, 1}, +}; + +static HRESULT fill_media_type(unsigned int index, AM_MEDIA_TYPE *mt) +{ + WAVEFORMATEX *format; + + if (index >= ARRAY_SIZE(audio_formats)) + return VFW_S_NO_MORE_ITEMS; + + if (!(format = CoTaskMemAlloc(sizeof(*format)))) + return E_OUTOFMEMORY; + + memset(format, 0, sizeof(WAVEFORMATEX)); + format->wFormatTag = WAVE_FORMAT_PCM; + format->nChannels = audio_formats[index].channels; + format->nSamplesPerSec = audio_formats[index].rate; + format->wBitsPerSample = audio_formats[index].depth; + format->nBlockAlign = audio_formats[index].channels * audio_formats[index].depth / 8; + format->nAvgBytesPerSec = format->nBlockAlign * format->nSamplesPerSec; + + memset(mt, 0, sizeof(AM_MEDIA_TYPE)); + mt->majortype = MEDIATYPE_Audio; + mt->subtype = MEDIASUBTYPE_PCM; + mt->bFixedSizeSamples = TRUE; + mt->lSampleSize = format->nBlockAlign; + mt->formattype = FORMAT_WaveFormatEx; + mt->cbFormat = sizeof(WAVEFORMATEX); + mt->pbFormat = (BYTE *)format; + + return S_OK; +} + +static HRESULT audio_record_source_get_media_type(struct strmbase_pin *iface, + unsigned int index, AM_MEDIA_TYPE *mt) +{ + return fill_media_type(index, mt); +} + static HRESULT WINAPI audio_record_source_DecideBufferSize(struct strmbase_source *iface, IMemAllocator *allocator, ALLOCATOR_PROPERTIES *props) { @@ -60,6 +128,7 @@ static HRESULT WINAPI audio_record_source_DecideBufferSize(struct strmbase_sourc
static const struct strmbase_source_ops source_ops = { + .base.pin_get_media_type = audio_record_source_get_media_type, .base.pin_query_interface = audio_record_source_query_interface, .pfnAttemptConnection = BaseOutputPinImpl_AttemptConnection, .pfnDecideAllocator = BaseOutputPinImpl_DecideAllocator, diff --git a/dlls/qcap/tests/audiorecord.c b/dlls/qcap/tests/audiorecord.c index 89964100ab6..6d06a5417bd 100644 --- a/dlls/qcap/tests/audiorecord.c +++ b/dlls/qcap/tests/audiorecord.c @@ -386,50 +386,48 @@ static void test_media_types(IBaseFilter *filter) ok(hr == S_OK, "Got hr %#lx.\n", hr);
hr = IEnumMediaTypes_Next(enummt, 1, &pmt, NULL); - todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); - if (hr == S_OK) + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + pformat = (void *)pmt->pbFormat; + ok(pformat->nChannels == 2, "Got %u channels.\n", pformat->nChannels); + ok(pformat->wBitsPerSample == 16, "Got depth %u.\n", pformat->wBitsPerSample); + ok(pformat->nSamplesPerSec == 44100, "Got sample rate %lu.\n", pformat->nSamplesPerSec); + + do { pformat = (void *)pmt->pbFormat; - ok(pformat->nChannels == 2, "Got %u channels.\n", pformat->nChannels); - ok(pformat->wBitsPerSample == 16, "Got depth %u.\n", pformat->wBitsPerSample); - ok(pformat->nSamplesPerSec == 44100, "Got sample rate %lu.\n", pformat->nSamplesPerSec);
- do - { - pformat = (void *)pmt->pbFormat; - - ok(IsEqualGUID(&pmt->majortype, &MEDIATYPE_Audio), "Got major type %s.\n", - debugstr_guid(&pmt->majortype)); - ok(IsEqualGUID(&pmt->subtype, &MEDIASUBTYPE_PCM), "Got subtype %s\n", - debugstr_guid(&pmt->subtype)); - ok(pmt->bFixedSizeSamples == TRUE, "Got fixed size %d.\n", pmt->bFixedSizeSamples); - ok(!pmt->bTemporalCompression, "Got temporal compression %d.\n", pmt->bTemporalCompression); - ok(pmt->lSampleSize == pformat->nBlockAlign, "Got sample size %lu.\n", pmt->lSampleSize); - ok(IsEqualGUID(&pmt->formattype, &FORMAT_WaveFormatEx), "Got format type %s.\n", - debugstr_guid(&pmt->formattype)); - ok(!pmt->pUnk, "Got pUnk %p.\n", pmt->pUnk); - ok(pmt->cbFormat == sizeof(WAVEFORMATEX), "Got format size %lu.\n", pmt->cbFormat); - - ok(pformat->wFormatTag == WAVE_FORMAT_PCM, "Got format %#x.\n", pformat->wFormatTag); - ok(pformat->nChannels == 1 || pformat->nChannels == 2, "Got %u channels.\n", pformat->nChannels); - ok(pformat->wBitsPerSample == 8 || pformat->wBitsPerSample == 16, "Got depth %u.\n", pformat->wBitsPerSample); - ok(pformat->nBlockAlign == pformat->nChannels * pformat->wBitsPerSample / 8, - "Got block align %u.\n", pformat->nBlockAlign); - ok(pformat->nAvgBytesPerSec == pformat->nSamplesPerSec * pformat->nBlockAlign, - "Got %lu bytes per second.\n", pformat->nAvgBytesPerSec); - ok(!pformat->cbSize, "Got size %u.\n", pformat->cbSize); - - strmbase_dump_media_type(pmt); - - hr = IPin_QueryAccept(pin, pmt); - ok(hr == S_OK, "Got hr %#lx.\n", hr); - - CoTaskMemFree(pmt->pbFormat); - CoTaskMemFree(pmt); - - hr = IEnumMediaTypes_Next(enummt, 1, &pmt, NULL); - } while (hr == S_OK); - } + ok(IsEqualGUID(&pmt->majortype, &MEDIATYPE_Audio), "Got major type %s.\n", + debugstr_guid(&pmt->majortype)); + ok(IsEqualGUID(&pmt->subtype, &MEDIASUBTYPE_PCM), "Got subtype %s\n", + debugstr_guid(&pmt->subtype)); + ok(pmt->bFixedSizeSamples == TRUE, "Got fixed size %d.\n", pmt->bFixedSizeSamples); + ok(!pmt->bTemporalCompression, "Got temporal compression %d.\n", pmt->bTemporalCompression); + ok(pmt->lSampleSize == pformat->nBlockAlign, "Got sample size %lu.\n", pmt->lSampleSize); + ok(IsEqualGUID(&pmt->formattype, &FORMAT_WaveFormatEx), "Got format type %s.\n", + debugstr_guid(&pmt->formattype)); + ok(!pmt->pUnk, "Got pUnk %p.\n", pmt->pUnk); + ok(pmt->cbFormat == sizeof(WAVEFORMATEX), "Got format size %lu.\n", pmt->cbFormat); + + ok(pformat->wFormatTag == WAVE_FORMAT_PCM, "Got format %#x.\n", pformat->wFormatTag); + ok(pformat->nChannels == 1 || pformat->nChannels == 2, "Got %u channels.\n", pformat->nChannels); + ok(pformat->wBitsPerSample == 8 || pformat->wBitsPerSample == 16, "Got depth %u.\n", pformat->wBitsPerSample); + ok(pformat->nBlockAlign == pformat->nChannels * pformat->wBitsPerSample / 8, + "Got block align %u.\n", pformat->nBlockAlign); + ok(pformat->nAvgBytesPerSec == pformat->nSamplesPerSec * pformat->nBlockAlign, + "Got %lu bytes per second.\n", pformat->nAvgBytesPerSec); + ok(!pformat->cbSize, "Got size %u.\n", pformat->cbSize); + + strmbase_dump_media_type(pmt); + + hr = IPin_QueryAccept(pin, pmt); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + CoTaskMemFree(pmt->pbFormat); + CoTaskMemFree(pmt); + + hr = IEnumMediaTypes_Next(enummt, 1, &pmt, NULL); + } while (hr == S_OK);
ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
@@ -522,7 +520,7 @@ static void test_stream_config(IBaseFilter *filter) hr = IAMStreamConfig_GetStreamCaps(config, count, &mt, (BYTE *)&caps); todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); hr = IEnumMediaTypes_Next(enummt, 1, &mt2, NULL); - ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
IEnumMediaTypes_Release(enummt);
From: Zebediah Figura zfigura@codeweavers.com
Needed by the Microsoft Silverlight configuration tool.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=36230 --- dlls/qcap/audiorecord.c | 46 +++++++++++++++++++++++++++++++---- dlls/qcap/tests/audiorecord.c | 26 +++++++++++--------- 2 files changed, 55 insertions(+), 17 deletions(-)
diff --git a/dlls/qcap/audiorecord.c b/dlls/qcap/audiorecord.c index 7107f22851b..ffd8e059b7b 100644 --- a/dlls/qcap/audiorecord.c +++ b/dlls/qcap/audiorecord.c @@ -174,15 +174,51 @@ static HRESULT WINAPI stream_config_GetFormat(IAMStreamConfig *iface, AM_MEDIA_T static HRESULT WINAPI stream_config_GetNumberOfCapabilities(IAMStreamConfig *iface, int *count, int *size) { - FIXME("iface %p, count %p, size %p, stub!\n", iface, count, size); - return E_NOTIMPL; + struct audio_record *filter = impl_from_IAMStreamConfig(iface); + + TRACE("filter %p, count %p, size %p.\n", filter, count, size); + + *count = ARRAY_SIZE(audio_formats); + *size = sizeof(AUDIO_STREAM_CONFIG_CAPS); + return S_OK; }
static HRESULT WINAPI stream_config_GetStreamCaps(IAMStreamConfig *iface, - int index, AM_MEDIA_TYPE **mt, BYTE *caps) + int index, AM_MEDIA_TYPE **ret_mt, BYTE *caps) { - FIXME("iface %p, index %d, mt %p, caps %p, stub!\n", iface, index, mt, caps); - return E_NOTIMPL; + struct audio_record *filter = impl_from_IAMStreamConfig(iface); + AUDIO_STREAM_CONFIG_CAPS *audio_caps = (void *)caps; + AM_MEDIA_TYPE *mt; + HRESULT hr; + + TRACE("filter %p, index %d, ret_mt %p, caps %p.\n", filter, index, ret_mt, caps); + + if (index >= ARRAY_SIZE(audio_formats)) + return S_FALSE; + + if (!(mt = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE)))) + return E_OUTOFMEMORY; + + if ((hr = fill_media_type(index, mt)) != S_OK) + { + CoTaskMemFree(mt); + return hr; + } + + *ret_mt = mt; + + audio_caps->guid = MEDIATYPE_Audio; + audio_caps->MinimumChannels = 1; + audio_caps->MaximumChannels = 2; + audio_caps->ChannelsGranularity = 1; + audio_caps->MinimumBitsPerSample = 8; + audio_caps->MaximumBitsPerSample = 16; + audio_caps->BitsPerSampleGranularity = 8; + audio_caps->MinimumSampleFrequency = 11025; + audio_caps->MaximumSampleFrequency = 44100; + audio_caps->SampleFrequencyGranularity = 11025; + + return S_OK; }
static const IAMStreamConfigVtbl stream_config_vtbl = diff --git a/dlls/qcap/tests/audiorecord.c b/dlls/qcap/tests/audiorecord.c index 6d06a5417bd..c64a8a83b2e 100644 --- a/dlls/qcap/tests/audiorecord.c +++ b/dlls/qcap/tests/audiorecord.c @@ -482,9 +482,9 @@ static void test_stream_config(IBaseFilter *filter)
count = size = 0xdeadbeef; hr = IAMStreamConfig_GetNumberOfCapabilities(config, &count, &size); - todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); - todo_wine ok(count && count != 0xdeadbeef, "Got count %d.\n", count); - todo_wine ok(size == sizeof(AUDIO_STREAM_CONFIG_CAPS), "Got size %d.\n", size); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(count && count != 0xdeadbeef, "Got count %d.\n", count); + ok(size == sizeof(AUDIO_STREAM_CONFIG_CAPS), "Got size %d.\n", size);
hr = IPin_EnumMediaTypes(source, &enummt); ok(hr == S_OK, "Got hr %#lx.\n", hr); @@ -518,9 +518,9 @@ static void test_stream_config(IBaseFilter *filter) }
hr = IAMStreamConfig_GetStreamCaps(config, count, &mt, (BYTE *)&caps); - todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + ok(hr == S_FALSE, "Got hr %#lx.\n", hr); hr = IEnumMediaTypes_Next(enummt, 1, &mt2, NULL); - todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
IEnumMediaTypes_Release(enummt);
@@ -551,19 +551,21 @@ static void test_stream_config(IBaseFilter *filter) winetest_push_context("Caps %u", i);
hr = IAMStreamConfig_GetStreamCaps(config, i, &mt, (BYTE *)&caps); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IAMStreamConfig_SetFormat(config, mt); + todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); + + hr = IAMStreamConfig_GetFormat(config, &mt2); todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); if (hr == S_OK) { - hr = IAMStreamConfig_SetFormat(config, mt); - todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); - - hr = IAMStreamConfig_GetFormat(config, &mt2); - todo_wine ok(hr == S_OK, "Got hr %#lx.\n", hr); ok(compare_media_types(mt, mt2), "Media types didn't match.\n"); DeleteMediaType(mt2); - - DeleteMediaType(mt); } + + DeleteMediaType(mt); + winetest_pop_context(); }
From: Zebediah Figura zfigura@codeweavers.com
--- dlls/qcap/audiorecord.c | 12 ++++++++++++ dlls/qcap/tests/audiorecord.c | 8 ++++---- 2 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/dlls/qcap/audiorecord.c b/dlls/qcap/audiorecord.c index ffd8e059b7b..d97d7fef19a 100644 --- a/dlls/qcap/audiorecord.c +++ b/dlls/qcap/audiorecord.c @@ -50,6 +50,17 @@ static HRESULT audio_record_source_query_interface(struct strmbase_pin *iface, R return S_OK; }
+static HRESULT audio_record_source_query_accept(struct strmbase_pin *iface, const AM_MEDIA_TYPE *mt) +{ + if (!IsEqualGUID(&mt->majortype, &MEDIATYPE_Audio)) + return S_FALSE; + + if (!IsEqualGUID(&mt->formattype, &FORMAT_WaveFormatEx)) + return S_FALSE; + + return S_OK; +} + static const struct { unsigned int rate; @@ -129,6 +140,7 @@ static HRESULT WINAPI audio_record_source_DecideBufferSize(struct strmbase_sourc static const struct strmbase_source_ops source_ops = { .base.pin_get_media_type = audio_record_source_get_media_type, + .base.pin_query_accept = audio_record_source_query_accept, .base.pin_query_interface = audio_record_source_query_interface, .pfnAttemptConnection = BaseOutputPinImpl_AttemptConnection, .pfnDecideAllocator = BaseOutputPinImpl_DecideAllocator, diff --git a/dlls/qcap/tests/audiorecord.c b/dlls/qcap/tests/audiorecord.c index c64a8a83b2e..0438b970ff1 100644 --- a/dlls/qcap/tests/audiorecord.c +++ b/dlls/qcap/tests/audiorecord.c @@ -443,18 +443,18 @@ static void test_media_types(IBaseFilter *filter) init_pcm_mt(&mt, &format, 1, 44100, 8); mt.majortype = MEDIATYPE_Stream; hr = IPin_QueryAccept(pin, &mt); - todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + ok(hr == S_FALSE, "Got hr %#lx.\n", hr); mt.majortype = GUID_NULL; hr = IPin_QueryAccept(pin, &mt); - todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
init_pcm_mt(&mt, &format, 1, 44100, 8); mt.formattype = FORMAT_None; hr = IPin_QueryAccept(pin, &mt); - todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + ok(hr == S_FALSE, "Got hr %#lx.\n", hr); mt.formattype = GUID_NULL; hr = IPin_QueryAccept(pin, &mt); - todo_wine ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
init_pcm_mt(&mt, &format, 1, 44100, 8); format.wFormatTag = 0xdead;