-- v2: winegstreamer: Use the correct name for WMADecMediaObject DMO. mf: Increase min_buffer_size to MF_MT_AUDIO_AVG_BYTES_PER_SECOND. mf: Implement SAR media type required attributes checks. winegstreamer: Set the MF_MT_AUDIO_AVG_BYTES_PER_SECOND attribute. mf: Return MF_E_NO_MORE_TYPE from AudioRenderer GetMediaTypeByIndex. mf/tests: Add required SAR media type attributes tests.
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/mf/tests/mf.c | 74 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 57 insertions(+), 17 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 996829c5e9a..c3d80c3dccc 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -4434,6 +4434,29 @@ static void check_sar_rate_support(IMFMediaSink *sink)
static void test_sar(void) { + static const struct attribute_desc input_type_desc_48000[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio), + ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float), + ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000), + ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2), + ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32), + ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8), + ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 8 * 48000), + {0}, + }; + static const struct attribute_desc input_type_desc_44100[] = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio), + ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float), + ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100), + ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2), + ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32), + ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8), + ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 8 * 44100), + {0}, + }; + IMFPresentationClock *present_clock, *present_clock2; IMFMediaType *mediatype, *mediatype2, *mediatype3; IMFClockStateSink *state_sink, *state_sink2; @@ -4443,17 +4466,16 @@ static void test_sar(void) IMFAudioStreamVolume *stream_volume; IMFMediaSink *sink, *sink2; IMFStreamSink *stream_sink; + UINT32 channel_count, rate; IMFAttributes *attributes; - DWORD i, id, flags, count; + DWORD id, flags, count; IMFActivate *activate; - UINT32 channel_count; MFCLOCK_STATE state; IMFClock *clock; IUnknown *unk; HRESULT hr; GUID guid; BOOL mute; - int found; LONG ref;
hr = CoInitialize(NULL); @@ -4613,21 +4635,40 @@ if (SUCCEEDED(hr)) ok(hr == S_OK, "Failed to get type count, hr %#lx.\n", hr); ok(!!count, "Unexpected type count %lu.\n", count);
- /* A number of same major/subtype entries are returned, with different degrees of finer format - details. Some incomplete types are not accepted, check that at least one of them is considered supported. */ + hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, count, &mediatype); + todo_wine + ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr); + + hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &mediatype); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaType_GetUINT32(mediatype, &MF_MT_AUDIO_SAMPLES_PER_SECOND, &rate); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(rate == 48000 || rate == 44100, "got rate %u.\n", rate); + IMFMediaType_Release(mediatype);
- for (i = 0, found = -1; i < count; ++i) - { - hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, i, &mediatype); - ok(hr == S_OK, "Failed to get media type, hr %#lx.\n", hr);
- if (SUCCEEDED(IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL))) - found = i; - IMFMediaType_Release(mediatype); + /* check required output media type attributes */
- if (found != -1) break; + hr = MFCreateMediaType(&mediatype); + ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr); + hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL); + todo_wine + ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr); + init_media_type(mediatype, rate == 44100 ? input_type_desc_44100 : input_type_desc_48000, 2); + for (int i = 1; i < (rate == 44100 ? ARRAY_SIZE(input_type_desc_44100) : ARRAY_SIZE(input_type_desc_48000)) - 1; ++i) + { + hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL); + todo_wine + ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr); + init_media_type(mediatype, rate == 44100 ? input_type_desc_44100 : input_type_desc_48000, i + 1); } - ok(found != -1, "Haven't found a supported type.\n"); + hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + init_media_type(mediatype, rate == 44100 ? input_type_desc_44100 : input_type_desc_48000, -1); + hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFMediaType_Release(mediatype); +
hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &mediatype); ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#lx.\n", hr); @@ -4652,10 +4693,9 @@ if (SUCCEEDED(hr)) hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, mediatype); ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr);
- hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, found, &mediatype2); + hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, count - 1, &mediatype2); ok(hr == S_OK, "Failed to get media type, hr %#lx.\n", hr); - - hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, found, &mediatype3); + hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, count - 1, &mediatype3); ok(hr == S_OK, "Failed to get media type, hr %#lx.\n", hr); ok(mediatype2 == mediatype3, "Unexpected instance.\n"); IMFMediaType_Release(mediatype3);
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/mf/sar.c | 9 ++++----- dlls/mf/tests/mf.c | 1 - 2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c index 5504cc17472..2aabb1fe10f 100644 --- a/dlls/mf/sar.c +++ b/dlls/mf/sar.c @@ -1531,12 +1531,11 @@ static HRESULT WINAPI audio_renderer_stream_type_handler_GetMediaTypeByIndex(IMF
TRACE("%p, %lu, %p.\n", iface, index, media_type);
- if (index == 0) - { - *media_type = renderer->media_type; - IMFMediaType_AddRef(*media_type); - } + if (index > 0) + return MF_E_NO_MORE_TYPES;
+ *media_type = renderer->media_type; + IMFMediaType_AddRef(*media_type); return S_OK; }
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index c3d80c3dccc..4638edbec76 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -4636,7 +4636,6 @@ if (SUCCEEDED(hr)) ok(!!count, "Unexpected type count %lu.\n", count);
hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, count, &mediatype); - todo_wine ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &mediatype);
From: R��mi Bernon rbernon@codeweavers.com
This is required by the Resampler transform, and will be used in next patch as well as for session buffer size heuristic. --- dlls/winegstreamer/mfplat.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c index 33557211243..9c27c5c7d60 100644 --- a/dlls/winegstreamer/mfplat.c +++ b/dlls/winegstreamer/mfplat.c @@ -698,8 +698,8 @@ static inline UINT64 make_uint64(UINT32 high, UINT32 low)
static IMFMediaType *mf_media_type_from_wg_format_audio(const struct wg_format *format) { + unsigned int i, block_align; IMFMediaType *type; - unsigned int i;
for (i = 0; i < ARRAY_SIZE(audio_formats); ++i) { @@ -715,7 +715,10 @@ static IMFMediaType *mf_media_type_from_wg_format_audio(const struct wg_format * IMFMediaType_SetUINT32(type, &MF_MT_AUDIO_NUM_CHANNELS, format->u.audio.channels); IMFMediaType_SetUINT32(type, &MF_MT_AUDIO_CHANNEL_MASK, format->u.audio.channel_mask); IMFMediaType_SetUINT32(type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE); - IMFMediaType_SetUINT32(type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, format->u.audio.channels * audio_formats[i].depth / 8); + + block_align = format->u.audio.channels * audio_formats[i].depth / 8; + IMFMediaType_SetUINT32(type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, block_align); + IMFMediaType_SetUINT32(type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, block_align * format->u.audio.rate);
return type; }
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/mf/sar.c | 49 ++++++++++++++++++++++++++++++++++++++-------- dlls/mf/tests/mf.c | 2 -- 2 files changed, 41 insertions(+), 10 deletions(-)
diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c index 2aabb1fe10f..84824f954dd 100644 --- a/dlls/mf/sar.c +++ b/dlls/mf/sar.c @@ -1499,20 +1499,57 @@ static ULONG WINAPI audio_renderer_stream_type_handler_Release(IMFMediaTypeHandl return IMFStreamSink_Release(&renderer->IMFStreamSink_iface); }
+static HRESULT check_media_type(IMFMediaType *type, IMFMediaType *current) +{ + static const GUID *required_attrs[] = + { + &MF_MT_AUDIO_SAMPLES_PER_SECOND, + &MF_MT_AUDIO_NUM_CHANNELS, + &MF_MT_AUDIO_BITS_PER_SAMPLE, + &MF_MT_AUDIO_BLOCK_ALIGNMENT, + &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, + }; + PROPVARIANT value; + BOOL result; + HRESULT hr; + GUID major; + int i; + + if (FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major))) + return hr; + if (!IsEqualGUID(&major, &MFMediaType_Audio)) + return MF_E_INVALIDMEDIATYPE; + + for (i = 0; SUCCEEDED(hr) && i < ARRAY_SIZE(required_attrs); ++i) + { + PropVariantInit(&value); + hr = IMFMediaType_GetItem(type, required_attrs[i], &value); + if (SUCCEEDED(hr)) + hr = IMFMediaType_CompareItem(current, required_attrs[i], &value, &result); + if (SUCCEEDED(hr) && !result) + hr = MF_E_INVALIDMEDIATYPE; + PropVariantClear(&value); + } + + if (FAILED(hr)) + return MF_E_INVALIDMEDIATYPE; + + return S_OK; +} + static HRESULT WINAPI audio_renderer_stream_type_handler_IsMediaTypeSupported(IMFMediaTypeHandler *iface, IMFMediaType *in_type, IMFMediaType **out_type) { struct audio_renderer *renderer = impl_from_IMFMediaTypeHandler(iface); - DWORD flags; HRESULT hr;
TRACE("%p, %p, %p.\n", iface, in_type, out_type);
EnterCriticalSection(&renderer->cs); - hr = IMFMediaType_IsEqual(renderer->media_type, in_type, &flags); + hr = check_media_type(in_type, renderer->media_type); LeaveCriticalSection(&renderer->cs);
- return hr != S_OK ? MF_E_INVALIDMEDIATYPE : hr; + return hr; }
static HRESULT WINAPI audio_renderer_stream_type_handler_GetMediaTypeCount(IMFMediaTypeHandler *iface, DWORD *count) @@ -1625,10 +1662,8 @@ static HRESULT WINAPI audio_renderer_stream_type_handler_SetCurrentMediaType(IMF IMFMediaType *media_type) { struct audio_renderer *renderer = impl_from_IMFMediaTypeHandler(iface); - const unsigned int test_flags = MF_MEDIATYPE_EQUAL_MAJOR_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_TYPES; BOOL compare_result; HRESULT hr = S_OK; - DWORD flags;
TRACE("%p, %p.\n", iface, media_type);
@@ -1636,7 +1671,7 @@ static HRESULT WINAPI audio_renderer_stream_type_handler_SetCurrentMediaType(IMF return E_POINTER;
EnterCriticalSection(&renderer->cs); - if (SUCCEEDED(IMFMediaType_IsEqual(renderer->media_type, media_type, &flags)) && ((flags & test_flags) == test_flags)) + if (SUCCEEDED(hr = check_media_type(media_type, renderer->media_type))) { if (renderer->current_media_type) IMFMediaType_Release(renderer->current_media_type); @@ -1745,8 +1780,6 @@ static HRESULT audio_renderer_collect_supported_types(struct audio_renderer *ren return hr; }
- IMFMediaType_DeleteItem(renderer->media_type, &MF_MT_AUDIO_PREFER_WAVEFORMATEX); - return hr; }
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 4638edbec76..10f69e73a8b 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -4651,13 +4651,11 @@ if (SUCCEEDED(hr)) hr = MFCreateMediaType(&mediatype); ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr); hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL); - todo_wine ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr); init_media_type(mediatype, rate == 44100 ? input_type_desc_44100 : input_type_desc_48000, 2); for (int i = 1; i < (rate == 44100 ? ARRAY_SIZE(input_type_desc_44100) : ARRAY_SIZE(input_type_desc_48000)) - 1; ++i) { hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL); - todo_wine ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#lx.\n", hr); init_media_type(mediatype, rate == 44100 ? input_type_desc_44100 : input_type_desc_48000, i + 1); }
From: R��mi Bernon rbernon@codeweavers.com
When it is specified. The Resampler transform exposes the block alignment in its output stream info cbSize, and the session then otherwise reads data one audio frame at a time. --- dlls/mf/session.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index a78e7cfc473..87fe77a730f 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -1438,6 +1438,7 @@ static HRESULT session_set_transform_stream_info(struct topo_node *node) struct transform_stream *streams; unsigned int block_alignment; IMFMediaType *media_type; + UINT32 bytes_per_second; GUID major = { 0 }; HRESULT hr;
@@ -1479,6 +1480,8 @@ static HRESULT session_set_transform_stream_info(struct topo_node *node) && SUCCEEDED(IMFMediaType_GetUINT32(media_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &block_alignment))) { streams[i].min_buffer_size = block_alignment; + if (SUCCEEDED(IMFMediaType_GetUINT32(media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &bytes_per_second))) + streams[i].min_buffer_size = max(streams[i].min_buffer_size, bytes_per_second); } IMFMediaType_Release(media_type); }
From: R��mi Bernon rbernon@codeweavers.com
--- dlls/mf/tests/mf.c | 1 - dlls/winegstreamer/main.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 10f69e73a8b..6621a0f0674 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -125,7 +125,6 @@ static void check_dmo(const GUID *class_id, const WCHAR *expect_name, const GUID
hr = DMOGetName(class_id, name); ok(hr == S_OK, "DMOGetName returned %#lx\n", hr); - todo_wine_if(!wcscmp(expect_name, L"WMAudio Decoder DMO")) ok(!wcscmp(name, expect_name), "got name %s\n", debugstr_w(name));
hr = DMOGetTypes(class_id, ARRAY_SIZE(input), &input_count, input, diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c index 20dcdccc606..189790db155 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -759,7 +759,7 @@ HRESULT WINAPI DllRegisterServer(void)
IFilterMapper2_Release(mapper);
- if (FAILED(hr = DMORegister(L"WMA Decoder DMO", &CLSID_WMADecMediaObject, &DMOCATEGORY_AUDIO_DECODER, + if (FAILED(hr = DMORegister(L"WMAudio Decoder DMO", &CLSID_WMADecMediaObject, &DMOCATEGORY_AUDIO_DECODER, 0, ARRAY_SIZE(wma_decoder_input), wma_decoder_input, ARRAY_SIZE(wma_decoder_output), wma_decoder_output))) return hr; if (FAILED(hr = DMORegister(L"Resampler DMO", &CLSID_CResamplerMediaObject, &DMOCATEGORY_AUDIO_EFFECT,
On Fri Jul 29 16:15:15 2022 +0000, R��mi Bernon wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/553/diffs?diff_id=6457&start_sha=25169943e882e9d6234366e8cbf04665978d5d9a#37de8fd303086366917ec7ce9239620f0961a3f0_1750_1783)
I'm manually checking the required attributes, it's pretty much the same set of attributes as for the transforms, and doesn't match any of the reported media types. I'm not really sure if it comes from anywhere. The `MF_MT_AUDIO_AVG_BYTES_PER_SECOND` attribute seems unnecessary, but is required.
The first type is just major + subtype + rate, and isn't accepted. The second has channel count + mask, which isn't a required attribute, and also isn't accepted. The fullest type is accepted, but has some superfluous attributes.
This merge request was approved by Nikolay Sivov.