[PATCH 2/5] mf: Add initial implementation of SAR stream type handler.
Nikolay Sivov
nsivov at codeweavers.com
Mon Apr 20 11:24:59 CDT 2020
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/mf/sar.c | 133 +++++++++++++++++++++++++++++++++++++++------
dlls/mf/tests/mf.c | 29 +++++++---
2 files changed, 138 insertions(+), 24 deletions(-)
diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c
index 3edaf06f01..80cfd94952 100644
--- a/dlls/mf/sar.c
+++ b/dlls/mf/sar.c
@@ -24,6 +24,7 @@
#include "mf_private.h"
#include "initguid.h"
#include "mmdeviceapi.h"
+#include "audioclient.h"
#include "wine/debug.h"
#include "wine/heap.h"
@@ -46,6 +47,9 @@ struct audio_renderer
IMFMediaEventQueue *event_queue;
IMFMediaEventQueue *stream_event_queue;
IMFPresentationClock *clock;
+ IMFMediaType *media_type;
+ IMFMediaType *current_media_type;
+ IMMDevice *device;
BOOL is_shut_down;
CRITICAL_SECTION cs;
};
@@ -162,6 +166,12 @@ static ULONG WINAPI audio_renderer_sink_Release(IMFMediaSink *iface)
IMFMediaEventQueue_Release(renderer->stream_event_queue);
if (renderer->clock)
IMFPresentationClock_Release(renderer->clock);
+ if (renderer->device)
+ IMMDevice_Release(renderer->device);
+ if (renderer->media_type)
+ IMFMediaType_Release(renderer->media_type);
+ if (renderer->current_media_type)
+ IMFMediaType_Release(renderer->current_media_type);
DeleteCriticalSection(&renderer->cs);
heap_free(renderer);
}
@@ -814,7 +824,7 @@ static const IMFAudioPolicyVtbl audio_renderer_policy_vtbl =
audio_renderer_policy_GetIconPath,
};
-static HRESULT sar_create_mmdevice(IMFAttributes *attributes, IMMDevice **device)
+static HRESULT sar_create_mmdevice(IMFAttributes *attributes, struct audio_renderer *renderer)
{
WCHAR *endpoint;
unsigned int length, role = eMultimedia;
@@ -845,11 +855,11 @@ static HRESULT sar_create_mmdevice(IMFAttributes *attributes, IMMDevice **device
&endpoint, &length)))
{
TRACE("Specified end point %s.\n", debugstr_w(endpoint));
- hr = IMMDeviceEnumerator_GetDevice(devenum, endpoint, device);
+ hr = IMMDeviceEnumerator_GetDevice(devenum, endpoint, &renderer->device);
CoTaskMemFree(endpoint);
}
else
- hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(devenum, eRender, role, device);
+ hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(devenum, eRender, role, &renderer->device);
if (FAILED(hr))
hr = MF_E_NO_AUDIO_PLAYBACK_DEVICE;
@@ -1057,40 +1067,92 @@ static ULONG WINAPI audio_renderer_stream_type_handler_Release(IMFMediaTypeHandl
static HRESULT WINAPI audio_renderer_stream_type_handler_IsMediaTypeSupported(IMFMediaTypeHandler *iface,
IMFMediaType *in_type, IMFMediaType **out_type)
{
- FIXME("%p, %p, %p.\n", iface, in_type, out_type);
+ struct audio_renderer *renderer = impl_from_IMFMediaTypeHandler(iface);
+ unsigned int flags;
+ HRESULT hr;
- return E_NOTIMPL;
+ TRACE("%p, %p, %p.\n", iface, in_type, out_type);
+
+ EnterCriticalSection(&renderer->cs);
+ hr = renderer->current_media_type && IMFMediaType_IsEqual(renderer->current_media_type, in_type, &flags) == S_OK ?
+ S_OK : MF_E_INVALIDMEDIATYPE;
+ LeaveCriticalSection(&renderer->cs);
+
+ return hr;
}
static HRESULT WINAPI audio_renderer_stream_type_handler_GetMediaTypeCount(IMFMediaTypeHandler *iface, DWORD *count)
{
- FIXME("%p, %p.\n", iface, count);
+ TRACE("%p, %p.\n", iface, count);
- return E_NOTIMPL;
+ *count = 1;
+
+ return S_OK;
}
static HRESULT WINAPI audio_renderer_stream_type_handler_GetMediaTypeByIndex(IMFMediaTypeHandler *iface, DWORD index,
IMFMediaType **media_type)
{
- FIXME("%p, %u, %p.\n", iface, index, media_type);
+ struct audio_renderer *renderer = impl_from_IMFMediaTypeHandler(iface);
- return E_NOTIMPL;
+ TRACE("%p, %u, %p.\n", iface, index, media_type);
+
+ if (index == 0)
+ {
+ *media_type = renderer->media_type;
+ IMFMediaType_AddRef(*media_type);
+ }
+
+ return S_OK;
}
static HRESULT WINAPI audio_renderer_stream_type_handler_SetCurrentMediaType(IMFMediaTypeHandler *iface,
IMFMediaType *media_type)
{
- FIXME("%p, %p.\n", iface, 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;
+ unsigned int flags;
+ HRESULT hr = S_OK;
- return E_NOTIMPL;
+ TRACE("%p, %p.\n", iface, media_type);
+
+ if (!media_type)
+ return E_POINTER;
+
+ EnterCriticalSection(&renderer->cs);
+ if (SUCCEEDED(IMFMediaType_IsEqual(renderer->media_type, media_type, &flags)) && ((flags & test_flags) == test_flags))
+ {
+ if (renderer->current_media_type)
+ IMFMediaType_Release(renderer->current_media_type);
+ renderer->current_media_type = media_type;
+ IMFMediaType_AddRef(renderer->current_media_type);
+ }
+ else
+ hr = MF_E_INVALIDMEDIATYPE;
+ LeaveCriticalSection(&renderer->cs);
+
+ return hr;
}
static HRESULT WINAPI audio_renderer_stream_type_handler_GetCurrentMediaType(IMFMediaTypeHandler *iface,
IMFMediaType **media_type)
{
- FIXME("%p, %p.\n", iface, media_type);
+ struct audio_renderer *renderer = impl_from_IMFMediaTypeHandler(iface);
+ HRESULT hr = S_OK;
- return E_NOTIMPL;
+ TRACE("%p, %p.\n", iface, media_type);
+
+ EnterCriticalSection(&renderer->cs);
+ if (renderer->current_media_type)
+ {
+ *media_type = renderer->current_media_type;
+ IMFMediaType_AddRef(*media_type);
+ }
+ else
+ hr = MF_E_NOT_INITIALIZED;
+ LeaveCriticalSection(&renderer->cs);
+
+ return hr;
}
static HRESULT WINAPI audio_renderer_stream_type_handler_GetMajorType(IMFMediaTypeHandler *iface, GUID *type)
@@ -1122,10 +1184,48 @@ static const IMFMediaTypeHandlerVtbl audio_renderer_stream_type_handler_vtbl =
audio_renderer_stream_type_handler_GetMajorType,
};
+static HRESULT audio_renderer_collect_supported_types(struct audio_renderer *renderer)
+{
+ IAudioClient *client;
+ WAVEFORMATEX *format;
+ HRESULT hr;
+
+ if (FAILED(hr = MFCreateMediaType(&renderer->media_type)))
+ return hr;
+
+ hr = IMMDevice_Activate(renderer->device, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, (void **)&client);
+ if (FAILED(hr))
+ {
+ WARN("Failed to create audio client, hr %#x.\n", hr);
+ return hr;
+ }
+
+ /* FIXME: */
+
+ hr = IAudioClient_GetMixFormat(client, &format);
+ IAudioClient_Release(client);
+ if (FAILED(hr))
+ {
+ WARN("Failed to get device audio format, hr %#x.\n", hr);
+ return hr;
+ }
+
+ hr = MFInitMediaTypeFromWaveFormatEx(renderer->media_type, format, format->cbSize + sizeof(*format));
+ CoTaskMemFree(format);
+ if (FAILED(hr))
+ {
+ WARN("Failed to initialize media type, hr %#x.\n", hr);
+ return hr;
+ }
+
+ IMFMediaType_DeleteItem(renderer->media_type, &MF_MT_AUDIO_PREFER_WAVEFORMATEX);
+
+ return hr;
+}
+
static HRESULT sar_create_object(IMFAttributes *attributes, void *user_context, IUnknown **obj)
{
struct audio_renderer *renderer;
- IMMDevice *device;
HRESULT hr;
TRACE("%p, %p, %p.\n", attributes, user_context, obj);
@@ -1152,10 +1252,11 @@ static HRESULT sar_create_object(IMFAttributes *attributes, void *user_context,
if (FAILED(hr = MFCreateEventQueue(&renderer->stream_event_queue)))
goto failed;
- if (FAILED(hr = sar_create_mmdevice(attributes, &device)))
+ if (FAILED(hr = sar_create_mmdevice(attributes, renderer)))
goto failed;
- IMMDevice_Release(device);
+ if (FAILED(hr = audio_renderer_collect_supported_types(renderer)))
+ goto failed;
*obj = (IUnknown *)&renderer->IMFMediaSink_iface;
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index 8933ea717c..511c6a8eb9 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -2722,9 +2722,10 @@ static void test_quality_manager(void)
static void test_sar(void)
{
IMFPresentationClock *present_clock, *present_clock2;
+ IMFMediaType *mediatype, *mediatype2, *mediatype3;
IMFMediaTypeHandler *handler, *handler2;
IMFPresentationTimeSource *time_source;
- IMFMediaType *mediatype, *mediatype2;
+ IMFSimpleAudioVolume *simple_volume;
IMFClockStateSink *state_sink;
IMFMediaSink *sink, *sink2;
IMFStreamSink *stream_sink;
@@ -2736,6 +2737,7 @@ static void test_sar(void)
IUnknown *unk;
HRESULT hr;
GUID guid;
+ BOOL mute;
hr = CoInitialize(NULL);
ok(hr == S_OK, "Failed to initialize, hr %#x.\n", hr);
@@ -2865,13 +2867,9 @@ todo_wine
count = 0;
hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count);
-todo_wine {
ok(hr == S_OK, "Failed to get type count, hr %#x.\n", hr);
ok(!!count, "Unexpected type count %u.\n", count);
-}
-if (SUCCEEDED(hr))
-{
hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &mediatype);
ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
@@ -2879,6 +2877,7 @@ if (SUCCEEDED(hr))
ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype, NULL);
+todo_wine
ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#x.\n", hr);
IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
@@ -2891,6 +2890,11 @@ if (SUCCEEDED(hr))
hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &mediatype2);
ok(hr == S_OK, "Failed to get media type, hr %#x.\n", hr);
+ hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &mediatype3);
+ ok(hr == S_OK, "Failed to get media type, hr %#x.\n", hr);
+ ok(mediatype2 == mediatype3, "Unexpected instance.\n");
+ IMFMediaType_Release(mediatype3);
+
hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype2, NULL);
ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
@@ -2904,6 +2908,10 @@ if (SUCCEEDED(hr))
ok(mediatype == mediatype2, "Unexpected instance.\n");
IMFMediaType_Release(mediatype);
+ /* Type is validated against current type. */
+ hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, mediatype2, NULL);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
IMFMediaType_Release(mediatype2);
/* Set partial type. */
@@ -2938,13 +2946,18 @@ if (SUCCEEDED(hr))
ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
IMFMediaTypeHandler_Release(handler);
-}
+
IMFStreamSink_Release(stream_sink);
/* Volume control */
- hr = MFGetService((IUnknown *)sink, &MR_POLICY_VOLUME_SERVICE, &IID_IMFSimpleAudioVolume, (void **)&unk);
+ hr = MFGetService((IUnknown *)sink, &MR_POLICY_VOLUME_SERVICE, &IID_IMFSimpleAudioVolume, (void **)&simple_volume);
ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
- IUnknown_Release(unk);
+
+ hr = IMFSimpleAudioVolume_GetMute(simple_volume, &mute);
+todo_wine
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ IMFSimpleAudioVolume_Release(simple_volume);
hr = MFGetService((IUnknown *)sink, &MR_STREAM_VOLUME_SERVICE, &IID_IMFAudioStreamVolume, (void **)&unk);
ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
--
2.26.1
More information about the wine-devel
mailing list