From 3139727a97a91b91e74d57ec97a8c19b0093b68e Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Mon, 27 May 2019 17:07:37 +0300 Subject: [PATCH] mf: Implement type handler methods for sample grabber stream. Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/mf/samplegrabber.c | 81 +++++++++++++++++++++------- dlls/mf/tests/mf.c | 117 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 172 insertions(+), 26 deletions(-) diff --git a/dlls/mf/samplegrabber.c b/dlls/mf/samplegrabber.c index b62502f4f1e..86dcb13a6c4 100644 --- a/dlls/mf/samplegrabber.c +++ b/dlls/mf/samplegrabber.c @@ -28,12 +28,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(mfplat); +struct sample_grabber; + struct sample_grabber_stream { IMFStreamSink IMFStreamSink_iface; IMFMediaTypeHandler IMFMediaTypeHandler_iface; LONG refcount; - IMFMediaSink *sink; + struct sample_grabber *sink; IMFMediaEventQueue *event_queue; }; @@ -136,7 +138,7 @@ static ULONG WINAPI sample_grabber_stream_Release(IMFStreamSink *iface) if (!refcount) { - IMFMediaSink_Release(stream->sink); + IMFMediaSink_Release(&stream->sink->IMFMediaSink_iface); if (stream->event_queue) { IMFMediaEventQueue_Shutdown(stream->event_queue); @@ -193,7 +195,7 @@ static HRESULT WINAPI sample_grabber_stream_GetMediaSink(IMFStreamSink *iface, I TRACE("%p, %p.\n", iface, sink); - *sink = stream->sink; + *sink = &stream->sink->IMFMediaSink_iface; IMFMediaSink_AddRef(*sink); return S_OK; @@ -281,47 +283,81 @@ static ULONG WINAPI sample_grabber_stream_type_handler_Release(IMFMediaTypeHandl static HRESULT WINAPI sample_grabber_stream_type_handler_IsMediaTypeSupported(IMFMediaTypeHandler *iface, IMFMediaType *in_type, IMFMediaType **out_type) { - FIXME("%p, %p, %p.\n", iface, in_type, out_type); + struct sample_grabber_stream *stream = impl_from_IMFMediaTypeHandler(iface); + const DWORD supported_flags = MF_MEDIATYPE_EQUAL_MAJOR_TYPES | MF_MEDIATYPE_EQUAL_FORMAT_TYPES; + DWORD flags; - return E_NOTIMPL; + TRACE("%p, %p, %p.\n", iface, in_type, out_type); + + if (!in_type) + return E_POINTER; + + if (IMFMediaType_IsEqual(stream->sink->media_type, in_type, &flags) == S_OK) + return S_OK; + + return (flags & supported_flags) == supported_flags ? S_OK : MF_E_INVALIDMEDIATYPE; } static HRESULT WINAPI sample_grabber_stream_type_handler_GetMediaTypeCount(IMFMediaTypeHandler *iface, DWORD *count) { - FIXME("%p, %p.\n", iface, count); + TRACE("%p, %p.\n", iface, count); - return E_NOTIMPL; + if (!count) + return E_POINTER; + + *count = 0; + + return S_OK; } static HRESULT WINAPI sample_grabber_stream_type_handler_GetMediaTypeByIndex(IMFMediaTypeHandler *iface, DWORD index, - IMFMediaType **type) + IMFMediaType **media_type) { - FIXME("%p, %u, %p.\n", iface, index, type); + TRACE("%p, %u, %p.\n", iface, index, media_type); - return E_NOTIMPL; + if (!media_type) + return E_POINTER; + + return MF_E_NO_MORE_TYPES; } static HRESULT WINAPI sample_grabber_stream_type_handler_SetCurrentMediaType(IMFMediaTypeHandler *iface, - IMFMediaType *type) + IMFMediaType *media_type) { - FIXME("%p, %p.\n", iface, type); + struct sample_grabber_stream *stream = impl_from_IMFMediaTypeHandler(iface); - return E_NOTIMPL; + TRACE("%p, %p.\n", iface, media_type); + + if (!media_type) + return E_POINTER; + + IMFMediaType_Release(stream->sink->media_type); + stream->sink->media_type = media_type; + IMFMediaType_AddRef(stream->sink->media_type); + + return S_OK; } static HRESULT WINAPI sample_grabber_stream_type_handler_GetCurrentMediaType(IMFMediaTypeHandler *iface, IMFMediaType **type) { - FIXME("%p, %p.\n", iface, type); + struct sample_grabber_stream *stream = impl_from_IMFMediaTypeHandler(iface); - return E_NOTIMPL; + TRACE("%p, %p.\n", iface, type); + + *type = stream->sink->media_type; + IMFMediaType_AddRef(*type); + + return S_OK; } static HRESULT WINAPI sample_grabber_stream_type_handler_GetMajorType(IMFMediaTypeHandler *iface, GUID *type) { - FIXME("%p, %p.\n", iface, type); + struct sample_grabber_stream *stream = impl_from_IMFMediaTypeHandler(iface); - return E_NOTIMPL; + TRACE("%p, %p.\n", iface, type); + + return IMFMediaType_GetMajorType(stream->sink->media_type, type); } static const IMFMediaTypeHandlerVtbl sample_grabber_stream_type_handler_vtbl = @@ -682,7 +718,7 @@ static const IMFClockStateSinkVtbl sample_grabber_clock_sink_vtbl = sample_grabber_clock_sink_OnClockSetRate, }; -static HRESULT sample_grabber_create_stream(IMFMediaSink *sink, IMFStreamSink **stream) +static HRESULT sample_grabber_create_stream(struct sample_grabber *sink, IMFStreamSink **stream) { struct sample_grabber_stream *object; HRESULT hr; @@ -695,7 +731,7 @@ static HRESULT sample_grabber_create_stream(IMFMediaSink *sink, IMFStreamSink ** object->IMFMediaTypeHandler_iface.lpVtbl = &sample_grabber_stream_type_handler_vtbl; object->refcount = 1; object->sink = sink; - IMFMediaSink_AddRef(object->sink); + IMFMediaSink_AddRef(&object->sink->IMFMediaSink_iface); if (FAILED(hr = MFCreateEventQueue(&object->event_queue))) goto failed; @@ -715,9 +751,14 @@ static HRESULT sample_grabber_create_object(IMFAttributes *attributes, void *use struct sample_grabber_activate_context *context = user_context; struct sample_grabber *object; HRESULT hr; + GUID guid; TRACE("%p, %p, %p.\n", attributes, user_context, obj); + /* At least major type is required. */ + if (FAILED(IMFMediaType_GetMajorType(context->media_type, &guid))) + return MF_E_INVALIDMEDIATYPE; + object = heap_alloc_zero(sizeof(*object)); if (!object) return E_OUTOFMEMORY; @@ -732,7 +773,7 @@ static HRESULT sample_grabber_create_object(IMFAttributes *attributes, void *use IMFMediaType_AddRef(object->media_type); InitializeCriticalSection(&object->cs); - if (FAILED(hr = sample_grabber_create_stream(&object->IMFMediaSink_iface, &object->stream))) + if (FAILED(hr = sample_grabber_create_stream(object, &object->stream))) goto failed; if (FAILED(hr = MFCreateEventQueue(&object->event_queue))) diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 317d611c2f6..b381daf882b 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -1638,17 +1638,23 @@ static IMFSampleGrabberSinkCallback grabber_callback = { &grabber_callback_vtbl static void test_sample_grabber(void) { + IMFMediaType *media_type, *media_type2, *media_type3; IMFMediaTypeHandler *handler, *handler2; + IMFPresentationTimeSource *time_source; IMFStreamSink *stream, *stream2; IMFClockStateSink *clocksink; + IMFPresentationClock *clock; IMFMediaEventGenerator *eg; IMFMediaSink *sink, *sink2; - IMFMediaType *media_type; DWORD flags, count, id; IMFActivate *activate; ULONG refcount; IUnknown *unk; HRESULT hr; + GUID guid; + + hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); + ok(hr == S_OK, "Failed to start up, hr %#x.\n", hr); hr = MFCreateMediaType(&media_type); ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr); @@ -1725,15 +1731,32 @@ static void test_sample_grabber(void) hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler); ok(hr == S_OK, "Failed to get type handler, hr %#x.\n", hr); hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count); -todo_wine { ok(hr == S_OK, "Failed to get media type count, hr %#x.\n", hr); ok(count == 0, "Unexpected count %u.\n", count); -} ok(handler == handler2, "Unexpected handler.\n"); IMFMediaTypeHandler_Release(handler); IMFMediaTypeHandler_Release(handler2); + /* Set clock. */ + hr = MFCreatePresentationClock(&clock); + ok(hr == S_OK, "Failed to create clock object, hr %#x.\n", hr); + + hr = IMFMediaSink_SetPresentationClock(sink, clock); + ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr); + + hr = MFCreateSystemTimeSource(&time_source); + ok(hr == S_OK, "Failed to create time source, hr %#x.\n", hr); + + hr = IMFPresentationClock_SetTimeSource(clock, time_source); + ok(hr == S_OK, "Failed to set time source, hr %#x.\n", hr); + IMFPresentationTimeSource_Release(time_source); + + hr = IMFMediaSink_SetPresentationClock(sink, clock); + ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr); + + IMFPresentationClock_Release(clock); + hr = IMFActivate_ShutdownObject(activate); todo_wine ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); @@ -1768,20 +1791,102 @@ todo_wine hr = IMFStreamSink_GetMediaTypeHandler(stream, &handler); ok(hr == S_OK, "Failed to get type handler, hr %#x.\n", hr); + /* On Win8+ this initialization happens automatically. */ + hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type); + ok(hr == S_OK, "Failed to set media type, hr %#x.\n", hr); + + hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + hr = IMFMediaTypeHandler_GetMediaTypeCount(handler, &count); -todo_wine { ok(hr == S_OK, "Failed to get media type count, hr %#x.\n", hr); ok(count == 0, "Unexpected count %u.\n", count); -} + + hr = IMFMediaTypeHandler_GetMajorType(handler, &guid); + ok(hr == S_OK, "Failed to get major type, hr %#x.\n", hr); + ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type %s.\n", wine_dbgstr_guid(&guid)); + + hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type2); + ok(hr == S_OK, "Failed to get current type, hr %#x.\n", hr); + ok(media_type2 == media_type, "Unexpected media type.\n"); + IMFMediaType_Release(media_type2); + + hr = MFCreateMediaType(&media_type2); + ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr); + + hr = IMFMediaType_SetGUID(media_type2, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + hr = IMFMediaType_SetGUID(media_type2, &MF_MT_SUBTYPE, &MFAudioFormat_PCM); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, media_type2); + ok(hr == S_OK, "Failed to get current type, hr %#x.\n", hr); + IMFMediaType_Release(media_type); + + hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &media_type); + ok(hr == S_OK, "Failed to get current type, hr %#x.\n", hr); + ok(media_type2 == media_type, "Unexpected media type.\n"); + IMFMediaType_Release(media_type); + + hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, &media_type); + ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaTypeHandler_GetMediaTypeByIndex(handler, 0, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type2, NULL); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = MFCreateMediaType(&media_type); + ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr); + + hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, NULL); + ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3); + ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + media_type3 = (void *)0xdeadbeef; + hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(media_type3 == (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3); + + hr = IMFMediaType_SetUINT32(media_type, &MF_MT_FIXED_SIZE_SAMPLES, 1); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + hr = IMFMediaType_SetUINT32(media_type, &MF_MT_SAMPLE_SIZE, 1024); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + media_type3 = (void *)0xdeadbeef; + hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, media_type, &media_type3); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(media_type3 == (void *)0xdeadbeef, "Unexpected media type %p.\n", media_type3); + + hr = IMFMediaTypeHandler_IsMediaTypeSupported(handler, NULL, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + IMFMediaTypeHandler_Release(handler); + IMFMediaType_Release(media_type2); + IMFMediaType_Release(media_type); + IMFMediaSink_Release(sink); IMFStreamSink_Release(stream); refcount = IMFActivate_Release(activate); ok(!refcount, "Unexpected refcount %u.\n", refcount); - IMFMediaType_Release(media_type); + hr = MFShutdown(); + ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr); } START_TEST(mf)