Signed-off-by: Nikolay Sivov [email protected] --- dlls/mf/tests/mf.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index f01385cc46c..7013939ab0b 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -1451,7 +1451,10 @@ todo_wine return;
hr = IMFMediaSource_CreatePresentationDescriptor(source, &pd); +todo_wine ok(hr == S_OK, "Failed to create descriptor, hr %#x.\n", hr); + if (FAILED(hr)) + return;
hr = IMFPresentationDescriptor_GetStreamDescriptorByIndex(pd, 0, &selected, &sd); ok(hr == S_OK, "Failed to get stream descriptor, hr %#x.\n", hr);
Signed-off-by: Nikolay Sivov [email protected] --- dlls/mf/evr.c | 70 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 55 insertions(+), 15 deletions(-)
diff --git a/dlls/mf/evr.c b/dlls/mf/evr.c index 93ad06b9493..161c0d9b730 100644 --- a/dlls/mf/evr.c +++ b/dlls/mf/evr.c @@ -409,11 +409,35 @@ static HRESULT WINAPI video_renderer_sink_GetCharacteristics(IMFMediaSink *iface return S_OK; }
+static HRESULT video_renderer_add_stream(struct video_renderer *renderer, unsigned int id, + IMFStreamSink **stream_sink) +{ + struct video_stream *stream; + HRESULT hr; + + if (!mf_array_reserve((void **)&renderer->streams, &renderer->stream_size, renderer->stream_count + 1, + sizeof(*renderer->streams))) + { + return E_OUTOFMEMORY; + } + + if (SUCCEEDED(hr = video_renderer_stream_create(renderer, id, &stream))) + { + if (stream_sink) + { + *stream_sink = &stream->IMFStreamSink_iface; + IMFStreamSink_AddRef(*stream_sink); + } + renderer->streams[renderer->stream_count++] = stream; + } + + return hr; +} + static HRESULT WINAPI video_renderer_sink_AddStreamSink(IMFMediaSink *iface, DWORD id, IMFMediaType *media_type, IMFStreamSink **stream_sink) { struct video_renderer *renderer = impl_from_IMFMediaSink(iface); - struct video_stream *stream; HRESULT hr;
TRACE("%p, %#x, %p, %p.\n", iface, id, media_type, stream_sink); @@ -425,20 +449,7 @@ static HRESULT WINAPI video_renderer_sink_AddStreamSink(IMFMediaSink *iface, DWO hr = MF_E_SHUTDOWN; else if (SUCCEEDED(hr = IMFTransform_AddInputStreams(renderer->mixer, 1, &id))) { - if (mf_array_reserve((void **)&renderer->streams, &renderer->stream_size, renderer->stream_count + 1, - sizeof(*renderer->streams))) - { - if (SUCCEEDED(hr = video_renderer_stream_create(renderer, id, &stream))) - { - *stream_sink = &stream->IMFStreamSink_iface; - IMFStreamSink_AddRef(*stream_sink); - renderer->streams[renderer->stream_count++] = stream; - } - } - else - hr = E_OUTOFMEMORY; - - if (FAILED(hr)) + if (FAILED(hr = video_renderer_add_stream(renderer, id, stream_sink))) IMFTransform_DeleteInputStream(renderer->mixer, id);
} @@ -1109,6 +1120,35 @@ static HRESULT video_renderer_create_mixer(struct video_renderer *renderer, IMFA IMFTopologyServiceLookupClient_Release(lookup_client); }
+ if (SUCCEEDED(hr)) + { + unsigned int input_count, output_count; + unsigned int *ids, *oids; + size_t i; + + /* Create stream sinks for inputs that mixer already has by default. */ + if (SUCCEEDED(IMFTransform_GetStreamCount(*out, &input_count, &output_count))) + { + ids = heap_calloc(input_count, sizeof(*ids)); + oids = heap_calloc(output_count, sizeof(*oids)); + + if (ids && oids) + { + if (SUCCEEDED(IMFTransform_GetStreamIDs(*out, input_count, ids, output_count, oids))) + { + for (i = 0; i < input_count; ++i) + { + video_renderer_add_stream(renderer, ids[i], NULL); + } + } + + } + + heap_free(ids); + heap_free(oids); + } + } + return hr; }
Signed-off-by: Nikolay Sivov [email protected] --- dlls/mf/evr.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 111 insertions(+), 3 deletions(-)
diff --git a/dlls/mf/evr.c b/dlls/mf/evr.c index 161c0d9b730..b27610e073a 100644 --- a/dlls/mf/evr.c +++ b/dlls/mf/evr.c @@ -37,6 +37,7 @@ struct video_renderer; struct video_stream { IMFStreamSink IMFStreamSink_iface; + IMFMediaTypeHandler IMFMediaTypeHandler_iface; LONG refcount; unsigned int id; struct video_renderer *parent; @@ -114,6 +115,11 @@ static struct video_stream *impl_from_IMFStreamSink(IMFStreamSink *iface) return CONTAINING_RECORD(iface, struct video_stream, IMFStreamSink_iface); }
+static struct video_stream *impl_from_IMFMediaTypeHandler(IMFMediaTypeHandler *iface) +{ + return CONTAINING_RECORD(iface, struct video_stream, IMFMediaTypeHandler_iface); +} + static void video_renderer_release_services(struct video_renderer *renderer) { IMFTopologyServiceLookupClient *lookup_client; @@ -137,12 +143,26 @@ static void video_renderer_release_services(struct video_renderer *renderer)
static HRESULT WINAPI video_stream_sink_QueryInterface(IMFStreamSink *iface, REFIID riid, void **obj) { + struct video_stream *stream = impl_from_IMFStreamSink(iface); + + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); + + *obj = NULL; + if (IsEqualIID(riid, &IID_IMFStreamSink) || IsEqualIID(riid, &IID_IMFMediaEventGenerator) || IsEqualIID(riid, &IID_IUnknown)) { *obj = iface; - IMFStreamSink_AddRef(iface); + } + else if (IsEqualIID(riid, &IID_IMFMediaTypeHandler)) + { + *obj = &stream->IMFMediaTypeHandler_iface; + } + + if (*obj) + { + IUnknown_AddRef((IUnknown *)*obj); return S_OK; }
@@ -252,9 +272,20 @@ static HRESULT WINAPI video_stream_sink_GetIdentifier(IMFStreamSink *iface, DWOR
static HRESULT WINAPI video_stream_sink_GetMediaTypeHandler(IMFStreamSink *iface, IMFMediaTypeHandler **handler) { - FIXME("%p, %p.\n", iface, handler); + struct video_stream *stream = impl_from_IMFStreamSink(iface);
- return E_NOTIMPL; + TRACE("%p, %p.\n", iface, handler); + + if (!handler) + return E_POINTER; + + if (!stream->parent) + return MF_E_STREAMSINK_REMOVED; + + *handler = &stream->IMFMediaTypeHandler_iface; + IMFMediaTypeHandler_AddRef(*handler); + + return S_OK; }
static HRESULT WINAPI video_stream_sink_ProcessSample(IMFStreamSink *iface, IMFSample *sample) @@ -296,6 +327,82 @@ static const IMFStreamSinkVtbl video_stream_sink_vtbl = video_stream_sink_Flush, };
+static HRESULT WINAPI video_stream_typehandler_QueryInterface(IMFMediaTypeHandler *iface, REFIID riid, + void **obj) +{ + struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface); + return IMFStreamSink_QueryInterface(&stream->IMFStreamSink_iface, riid, obj); +} + +static ULONG WINAPI video_stream_typehandler_AddRef(IMFMediaTypeHandler *iface) +{ + struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface); + return IMFStreamSink_AddRef(&stream->IMFStreamSink_iface); +} + +static ULONG WINAPI video_stream_typehandler_Release(IMFMediaTypeHandler *iface) +{ + struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface); + return IMFStreamSink_Release(&stream->IMFStreamSink_iface); +} + +static HRESULT WINAPI video_stream_typehandler_IsMediaTypeSupported(IMFMediaTypeHandler *iface, + IMFMediaType *in_type, IMFMediaType **out_type) +{ + FIXME("%p, %p, %p.\n", iface, in_type, out_type); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_stream_typehandler_GetMediaTypeCount(IMFMediaTypeHandler *iface, DWORD *count) +{ + FIXME("%p, %p.\n", iface, count); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_stream_typehandler_GetMediaTypeByIndex(IMFMediaTypeHandler *iface, DWORD index, + IMFMediaType **type) +{ + FIXME("%p, %u, %p.\n", iface, index, type); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_stream_typehandler_SetCurrentMediaType(IMFMediaTypeHandler *iface, IMFMediaType *type) +{ + FIXME("%p, %p.\n", iface, type); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_stream_typehandler_GetCurrentMediaType(IMFMediaTypeHandler *iface, IMFMediaType **type) +{ + FIXME("%p, %p.\n", iface, type); + + return E_NOTIMPL; +} + +static HRESULT WINAPI video_stream_typehandler_GetMajorType(IMFMediaTypeHandler *iface, GUID *type) +{ + FIXME("%p, %p.\n", iface, type); + + return E_NOTIMPL; +} + +static const IMFMediaTypeHandlerVtbl video_stream_type_handler_vtbl = +{ + video_stream_typehandler_QueryInterface, + video_stream_typehandler_AddRef, + video_stream_typehandler_Release, + video_stream_typehandler_IsMediaTypeSupported, + video_stream_typehandler_GetMediaTypeCount, + video_stream_typehandler_GetMediaTypeByIndex, + video_stream_typehandler_SetCurrentMediaType, + video_stream_typehandler_GetCurrentMediaType, + video_stream_typehandler_GetMajorType, +}; + static HRESULT video_renderer_stream_create(struct video_renderer *renderer, unsigned int id, struct video_stream **ret) { @@ -306,6 +413,7 @@ static HRESULT video_renderer_stream_create(struct video_renderer *renderer, uns return E_OUTOFMEMORY;
stream->IMFStreamSink_iface.lpVtbl = &video_stream_sink_vtbl; + stream->IMFMediaTypeHandler_iface.lpVtbl = &video_stream_type_handler_vtbl; stream->refcount = 1;
if (FAILED(hr = MFCreateEventQueue(&stream->event_queue)))
Signed-off-by: Nikolay Sivov [email protected] --- dlls/mf/evr.c | 13 +++++++++++-- dlls/mf/tests/mf.c | 20 ++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/dlls/mf/evr.c b/dlls/mf/evr.c index b27610e073a..31bc110ea48 100644 --- a/dlls/mf/evr.c +++ b/dlls/mf/evr.c @@ -385,9 +385,18 @@ static HRESULT WINAPI video_stream_typehandler_GetCurrentMediaType(IMFMediaTypeH
static HRESULT WINAPI video_stream_typehandler_GetMajorType(IMFMediaTypeHandler *iface, GUID *type) { - FIXME("%p, %p.\n", iface, type); + struct video_stream *stream = impl_from_IMFMediaTypeHandler(iface);
- return E_NOTIMPL; + TRACE("%p, %p.\n", iface, type); + + if (!stream->parent) + return MF_E_STREAMSINK_REMOVED; + + if (!type) + return E_POINTER; + + memcpy(type, &MFMediaType_Video, sizeof(*type)); + return S_OK; }
static const IMFMediaTypeHandlerVtbl video_stream_type_handler_vtbl = diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 7013939ab0b..2c02b1d8e54 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -3236,16 +3236,19 @@ todo_wine static void test_evr(void) { IMFMediaEventGenerator *ev_generator; + IMFMediaTypeHandler *type_handler; IMFVideoRenderer *video_renderer; IMFClockStateSink *clock_sink; IMFMediaSinkPreroll *preroll; IMFMediaSink *sink, *sink2; + IMFStreamSink *stream_sink; IMFActivate *activate; DWORD flags, count; IMFGetService *gs; IUnknown *unk; UINT64 value; HRESULT hr; + GUID guid;
hr = CoInitialize(NULL); ok(hr == S_OK, "Failed to initialize, hr %#x.\n", hr); @@ -3267,6 +3270,23 @@ static void test_evr(void) hr = IMFActivate_ActivateObject(activate, &IID_IMFMediaSink, (void **)&sink); ok(hr == S_OK, "Failed to activate, hr %#x.\n", hr);
+ /* Primary stream type handler. */ + hr = IMFMediaSink_GetStreamSinkById(sink, 0, &stream_sink); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &type_handler); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaTypeHandler_GetMajorType(type_handler, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + hr = IMFMediaTypeHandler_GetMajorType(type_handler, &guid); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected type %s.\n", wine_dbgstr_guid(&guid)); + + IMFStreamSink_Release(stream_sink); + IMFMediaTypeHandler_Release(type_handler); + hr = IMFMediaSink_GetCharacteristics(sink, &flags); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); ok(flags == (MEDIASINK_CAN_PREROLL | MEDIASINK_CLOCK_REQUIRED), "Unexpected flags %#x.\n", flags);
Signed-off-by: Nikolay Sivov [email protected] --- dlls/evr/mixer.c | 24 ++++++++++++++++++++---- dlls/evr/tests/evr.c | 15 ++++++++++++++- include/evr.idl | 10 ++++++++++ 3 files changed, 44 insertions(+), 5 deletions(-)
diff --git a/dlls/evr/mixer.c b/dlls/evr/mixer.c index 7e08beae353..c7dbf8ff975 100644 --- a/dlls/evr/mixer.c +++ b/dlls/evr/mixer.c @@ -73,6 +73,7 @@ struct video_mixer IDirect3DDeviceManager9 *device_manager; IMediaEventSink *event_sink; IMFAttributes *attributes; + unsigned int mixing_flags; CRITICAL_SECTION cs; };
@@ -1008,16 +1009,31 @@ static HRESULT WINAPI video_mixer_control_GetStreamOutputRect(IMFVideoMixerContr
static HRESULT WINAPI video_mixer_control_SetMixingPrefs(IMFVideoMixerControl2 *iface, DWORD flags) { - FIXME("%p, %#x.\n", iface, flags); + struct video_mixer *mixer = impl_from_IMFVideoMixerControl2(iface);
- return E_NOTIMPL; + TRACE("%p, %#x.\n", iface, flags); + + EnterCriticalSection(&mixer->cs); + mixer->mixing_flags = flags; + LeaveCriticalSection(&mixer->cs); + + return S_OK; }
static HRESULT WINAPI video_mixer_control_GetMixingPrefs(IMFVideoMixerControl2 *iface, DWORD *flags) { - FIXME("%p, %p.\n", iface, flags); + struct video_mixer *mixer = impl_from_IMFVideoMixerControl2(iface);
- return E_NOTIMPL; + TRACE("%p, %p.\n", iface, flags); + + if (!flags) + return E_POINTER; + + EnterCriticalSection(&mixer->cs); + *flags = mixer->mixing_flags; + LeaveCriticalSection(&mixer->cs); + + return S_OK; }
static const IMFVideoMixerControl2Vtbl video_mixer_control_vtbl = diff --git a/dlls/evr/tests/evr.c b/dlls/evr/tests/evr.c index ba97eba53d1..92810b516a7 100644 --- a/dlls/evr/tests/evr.c +++ b/dlls/evr/tests/evr.c @@ -414,6 +414,7 @@ static void test_default_mixer(void) { DWORD input_min, input_max, output_min, output_max; IMFAttributes *attributes, *attributes2; + IMFVideoMixerControl2 *mixer_control2; MFT_OUTPUT_STREAM_INFO output_info; MFT_INPUT_STREAM_INFO input_info; DWORD input_count, output_count; @@ -424,12 +425,12 @@ static void test_default_mixer(void) IMFTransform *transform; DXVA2_ValueRange range; DXVA2_Fixed32 value; + DWORD flags, count; IMFGetService *gs; COLORREF color; unsigned int i; DWORD ids[16]; IUnknown *unk; - DWORD count; GUID *guids; HRESULT hr; IID iid; @@ -455,6 +456,18 @@ static void test_default_mixer(void) ok(hr == S_OK, "Unexpected hr %#x.\n", hr); IUnknown_Release(unk);
+ if (SUCCEEDED(IMFGetService_GetService(gs, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerControl2, (void **)&mixer_control2))) + { + hr = IMFVideoMixerControl2_GetMixingPrefs(mixer_control2, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + hr = IMFVideoMixerControl2_GetMixingPrefs(mixer_control2, &flags); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!flags, "Unexpected flags %#x.\n", flags); + + IMFVideoMixerControl2_Release(mixer_control2); + } + hr = IMFVideoProcessor_GetBackgroundColor(processor, NULL); ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
diff --git a/include/evr.idl b/include/evr.idl index 6369a39b2f3..77c46a075f1 100644 --- a/include/evr.idl +++ b/include/evr.idl @@ -184,6 +184,16 @@ interface IMFVideoMixerControl : IUnknown ); }
+typedef enum _MFVideoMixPrefs +{ + MFVideoMixPrefs_ForceHalfInterlace = 0x00000001, + MFVideoMixPrefs_AllowDropToHalfInterlace = 0x00000002, + MFVideoMixPrefs_AllowDropToBob = 0x00000004, + MFVideoMixPrefs_ForceBob = 0x00000008, + MFVideoMixPrefs_EnableRotation = 0x00000010, + MFVideoMixPrefs_Mask = 0x0000001f, +} MFVideoMixPrefs; + [ object, uuid(8459616d-966e-4930-b658-54fa7e5a16d3)