mf: Add initial implementation of SAR stream type handler.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
198fa490a4
commit
d2c736e1ba
133
dlls/mf/sar.c
133
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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue