qcap/audiorecord: Implement IAMBufferNegotiation::SuggestAllocatorProperties().

Needed by the Microsoft Silverlight configuration tool.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=36230
This commit is contained in:
Zebediah Figura 2023-05-04 15:51:15 -05:00 committed by Alexandre Julliard
parent c41ba79df7
commit 38b0a4005a
2 changed files with 76 additions and 6 deletions

View file

@ -46,6 +46,7 @@ struct audio_record
CRITICAL_SECTION state_cs; CRITICAL_SECTION state_cs;
AM_MEDIA_TYPE format; AM_MEDIA_TYPE format;
ALLOCATOR_PROPERTIES props;
}; };
static struct audio_record *impl_from_strmbase_filter(struct strmbase_filter *filter) static struct audio_record *impl_from_strmbase_filter(struct strmbase_filter *filter)
@ -158,12 +159,18 @@ static HRESULT WINAPI audio_record_source_DecideBufferSize(struct strmbase_sourc
MMRESULT ret; MMRESULT ret;
HRESULT hr; HRESULT hr;
props->cBuffers = 4; props->cBuffers = (filter->props.cBuffers == -1) ? 4 : filter->props.cBuffers;
/* This is the algorithm that native uses. The alignment to an even number /* This is the algorithm that native uses. The alignment to an even number
* doesn't make much sense, and may be a bug. */ * doesn't make much sense, and may be a bug. */
props->cbBuffer = (format->nAvgBytesPerSec / 2) & ~1; if (filter->props.cbBuffer == -1)
props->cbAlign = 1; props->cbBuffer = (format->nAvgBytesPerSec / 2) & ~1;
props->cbPrefix = 0; else
props->cbBuffer = filter->props.cbBuffer & ~1;
if (filter->props.cbAlign == -1 || filter->props.cbAlign == 0)
props->cbAlign = 1;
else
props->cbAlign = filter->props.cbAlign;
props->cbPrefix = (filter->props.cbPrefix == -1) ? 0 : filter->props.cbPrefix;
if (FAILED(hr = IMemAllocator_SetProperties(allocator, props, &ret_props))) if (FAILED(hr = IMemAllocator_SetProperties(allocator, props, &ret_props)))
return hr; return hr;
@ -356,10 +363,17 @@ static ULONG WINAPI buffer_negotiation_Release(IAMBufferNegotiation *iface)
static HRESULT WINAPI buffer_negotiation_SuggestAllocatorProperties( static HRESULT WINAPI buffer_negotiation_SuggestAllocatorProperties(
IAMBufferNegotiation *iface, const ALLOCATOR_PROPERTIES *props) IAMBufferNegotiation *iface, const ALLOCATOR_PROPERTIES *props)
{ {
FIXME("iface %p, props %p, stub!\n", iface, props); struct audio_record *filter = impl_from_IAMBufferNegotiation(iface);
TRACE("filter %p, props %p.\n", filter, props);
TRACE("Requested %ld buffers, size %ld, alignment %ld, prefix %ld.\n", TRACE("Requested %ld buffers, size %ld, alignment %ld, prefix %ld.\n",
props->cBuffers, props->cbBuffer, props->cbAlign, props->cbPrefix); props->cBuffers, props->cbBuffer, props->cbAlign, props->cbPrefix);
return E_NOTIMPL;
EnterCriticalSection(&filter->state_cs);
filter->props = *props;
LeaveCriticalSection(&filter->state_cs);
return S_OK;
} }
static HRESULT WINAPI buffer_negotiation_GetAllocatorProperties( static HRESULT WINAPI buffer_negotiation_GetAllocatorProperties(
@ -788,6 +802,11 @@ HRESULT audio_record_create(IUnknown *outer, IUnknown **out)
return hr; return hr;
} }
object->props.cBuffers = -1;
object->props.cbBuffer = -1;
object->props.cbAlign = -1;
object->props.cbPrefix = -1;
object->IPersistPropertyBag_iface.lpVtbl = &PersistPropertyBagVtbl; object->IPersistPropertyBag_iface.lpVtbl = &PersistPropertyBagVtbl;
strmbase_filter_init(&object->filter, outer, &CLSID_AudioRecord, &filter_ops); strmbase_filter_init(&object->filter, outer, &CLSID_AudioRecord, &filter_ops);

View file

@ -618,6 +618,7 @@ static void test_source_allocator(IFilterGraph2 *graph, IMediaControl *control,
IPin *source, struct testfilter *testsink) IPin *source, struct testfilter *testsink)
{ {
ALLOCATOR_PROPERTIES props, req_props = {2, 3200, 32, 0}; ALLOCATOR_PROPERTIES props, req_props = {2, 3200, 32, 0};
IAMBufferNegotiation *negotiation;
IMemAllocator *allocator; IMemAllocator *allocator;
IMediaSample *sample; IMediaSample *sample;
WAVEFORMATEX format; WAVEFORMATEX format;
@ -692,6 +693,56 @@ static void test_source_allocator(IFilterGraph2 *graph, IMediaControl *control,
IFilterGraph2_Disconnect(graph, source); IFilterGraph2_Disconnect(graph, source);
IFilterGraph2_Disconnect(graph, &testsink->sink.pin.IPin_iface); IFilterGraph2_Disconnect(graph, &testsink->sink.pin.IPin_iface);
/* Test IAMBufferNegotiation. *This* is respected. */
IPin_QueryInterface(source, &IID_IAMBufferNegotiation, (void **)&negotiation);
hr = IAMBufferNegotiation_SuggestAllocatorProperties(negotiation, &req_props);
ok(hr == S_OK, "Got hr %#lx.\n", hr);
init_pcm_mt(&mt, &format, 1, 32000, 16);
hr = IFilterGraph2_ConnectDirect(graph, source, &testsink->sink.pin.IPin_iface, &mt);
ok(hr == S_OK, "Got hr %#lx.\n", hr);
todo_wine ok(testsink->sink.pAllocator && testsink->sink.pAllocator != allocator,
"Got unexpected allocator %p.\n", testsink->sink.pAllocator);
hr = IMemAllocator_GetProperties(testsink->sink.pAllocator, &props);
ok(hr == S_OK, "Got hr %#lx.\n", hr);
ok(props.cBuffers == req_props.cBuffers, "Got %ld buffers.\n", props.cBuffers);
ok(props.cbBuffer == req_props.cbBuffer, "Got size %ld.\n", props.cbBuffer);
ok(props.cbAlign == req_props.cbAlign, "Got alignment %ld.\n", props.cbAlign);
ok(props.cbPrefix == req_props.cbPrefix, "Got prefix %ld.\n", props.cbPrefix);
IFilterGraph2_Disconnect(graph, source);
IFilterGraph2_Disconnect(graph, &testsink->sink.pin.IPin_iface);
for (req_props.cbBuffer = 32000; req_props.cbBuffer < 32050; ++req_props.cbBuffer)
{
req_props.cBuffers = -1;
req_props.cbAlign = 0;
hr = IAMBufferNegotiation_SuggestAllocatorProperties(negotiation, &req_props);
ok(hr == S_OK, "Got hr %#lx.\n", hr);
init_pcm_mt(&mt, &format, 1, 32000, 8);
hr = IFilterGraph2_ConnectDirect(graph, source, &testsink->sink.pin.IPin_iface, &mt);
ok(hr == S_OK, "Got hr %#lx.\n", hr);
todo_wine ok(testsink->sink.pAllocator && testsink->sink.pAllocator != allocator,
"Got unexpected allocator %p.\n", testsink->sink.pAllocator);
hr = IMemAllocator_GetProperties(testsink->sink.pAllocator, &props);
ok(hr == S_OK, "Got hr %#lx.\n", hr);
ok(props.cBuffers == 4, "Got %ld buffers.\n", props.cBuffers);
ok(props.cbBuffer == (req_props.cbBuffer & ~1),
"Got size %ld for %ld.\n", props.cbBuffer, req_props.cbBuffer);
ok(props.cbAlign == 1, "Got alignment %ld.\n", props.cbAlign);
ok(props.cbPrefix == req_props.cbPrefix, "Got prefix %ld.\n", props.cbPrefix);
IFilterGraph2_Disconnect(graph, source);
IFilterGraph2_Disconnect(graph, &testsink->sink.pin.IPin_iface);
}
IAMBufferNegotiation_Release(negotiation);
} }
static void test_filter_state(IFilterGraph2 *graph, IMediaControl *control, static void test_filter_state(IFilterGraph2 *graph, IMediaControl *control,