[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