evr: Forward some known interface queries for MR_VIDEO_MIXER_SERVICE.
[wine.git] / dlls / evr / tests / evr.c
blob5bfa87014d8738a48971f17f5e17f097899996b0
1 /*
2 * Enhanced Video Renderer filter unit tests
4 * Copyright 2018 Zebediah Figura
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
23 #include "dshow.h"
24 #include "wine/test.h"
25 #include "d3d9.h"
26 #include "evr.h"
27 #include "mferror.h"
28 #include "mfapi.h"
29 #include "initguid.h"
30 #include "evr9.h"
32 static const WCHAR sink_id[] = {'E','V','R',' ','I','n','p','u','t','0',0};
34 static HRESULT (WINAPI *pMFCreateVideoMediaTypeFromSubtype)(const GUID *subtype, IMFVideoMediaType **video_type);
36 static HWND create_window(void)
38 RECT r = {0, 0, 640, 480};
40 AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW | WS_VISIBLE, FALSE);
42 return CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
43 0, 0, r.right - r.left, r.bottom - r.top, NULL, NULL, NULL, NULL);
46 static IDirect3DDevice9 *create_device(IDirect3D9 *d3d9, HWND focus_window)
48 D3DPRESENT_PARAMETERS present_parameters = {0};
49 IDirect3DDevice9 *device = NULL;
51 present_parameters.BackBufferWidth = 640;
52 present_parameters.BackBufferHeight = 480;
53 present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
54 present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
55 present_parameters.hDeviceWindow = focus_window;
56 present_parameters.Windowed = TRUE;
57 present_parameters.EnableAutoDepthStencil = TRUE;
58 present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
60 IDirect3D9_CreateDevice(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, focus_window,
61 D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device);
63 return device;
66 static IBaseFilter *create_evr(void)
68 IBaseFilter *filter = NULL;
69 HRESULT hr = CoCreateInstance(&CLSID_EnhancedVideoRenderer, NULL, CLSCTX_INPROC_SERVER,
70 &IID_IBaseFilter, (void **)&filter);
71 ok(hr == S_OK, "Got hr %#x.\n", hr);
72 return filter;
75 static ULONG get_refcount(void *iface)
77 IUnknown *unknown = iface;
78 IUnknown_AddRef(unknown);
79 return IUnknown_Release(unknown);
82 static const GUID test_iid = {0x33333333};
83 static LONG outer_ref = 1;
85 static HRESULT WINAPI outer_QueryInterface(IUnknown *iface, REFIID iid, void **out)
87 if (IsEqualGUID(iid, &IID_IUnknown)
88 || IsEqualGUID(iid, &IID_IBaseFilter)
89 || IsEqualGUID(iid, &test_iid))
91 *out = (IUnknown *)0xdeadbeef;
92 return S_OK;
94 ok(0, "unexpected call %s\n", wine_dbgstr_guid(iid));
95 return E_NOINTERFACE;
98 static ULONG WINAPI outer_AddRef(IUnknown *iface)
100 return InterlockedIncrement(&outer_ref);
103 static ULONG WINAPI outer_Release(IUnknown *iface)
105 return InterlockedDecrement(&outer_ref);
108 static const IUnknownVtbl outer_vtbl =
110 outer_QueryInterface,
111 outer_AddRef,
112 outer_Release,
115 static IUnknown test_outer = {&outer_vtbl};
117 static void test_aggregation(void)
119 IBaseFilter *filter, *filter2;
120 IUnknown *unk, *unk2;
121 HRESULT hr;
122 ULONG ref;
124 filter = (IBaseFilter *)0xdeadbeef;
125 hr = CoCreateInstance(&CLSID_EnhancedVideoRenderer, &test_outer, CLSCTX_INPROC_SERVER,
126 &IID_IBaseFilter, (void **)&filter);
127 ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr);
128 ok(!filter, "Got interface %p.\n", filter);
130 hr = CoCreateInstance(&CLSID_EnhancedVideoRenderer, &test_outer, CLSCTX_INPROC_SERVER,
131 &IID_IUnknown, (void **)&unk);
132 ok(hr == S_OK, "Got hr %#x.\n", hr);
133 ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
134 ok(unk != &test_outer, "Returned IUnknown should not be outer IUnknown.\n");
135 ref = get_refcount(unk);
136 ok(ref == 1, "Got unexpected refcount %d.\n", ref);
138 ref = IUnknown_AddRef(unk);
139 ok(ref == 2, "Got unexpected refcount %d.\n", ref);
140 ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
142 ref = IUnknown_Release(unk);
143 ok(ref == 1, "Got unexpected refcount %d.\n", ref);
144 ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
146 hr = IUnknown_QueryInterface(unk, &IID_IUnknown, (void **)&unk2);
147 ok(hr == S_OK, "Got hr %#x.\n", hr);
148 ok(unk2 == unk, "Got unexpected IUnknown %p.\n", unk2);
149 IUnknown_Release(unk2);
151 hr = IUnknown_QueryInterface(unk, &IID_IBaseFilter, (void **)&filter);
152 ok(hr == S_OK, "Got hr %#x.\n", hr);
154 hr = IBaseFilter_QueryInterface(filter, &IID_IUnknown, (void **)&unk2);
155 ok(hr == S_OK, "Got hr %#x.\n", hr);
156 ok(unk2 == (IUnknown *)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2);
158 hr = IBaseFilter_QueryInterface(filter, &IID_IBaseFilter, (void **)&filter2);
159 ok(hr == S_OK, "Got hr %#x.\n", hr);
160 ok(filter2 == (IBaseFilter *)0xdeadbeef, "Got unexpected IBaseFilter %p.\n", filter2);
162 hr = IUnknown_QueryInterface(unk, &test_iid, (void **)&unk2);
163 ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr);
164 ok(!unk2, "Got unexpected IUnknown %p.\n", unk2);
166 hr = IBaseFilter_QueryInterface(filter, &test_iid, (void **)&unk2);
167 ok(hr == S_OK, "Got hr %#x.\n", hr);
168 ok(unk2 == (IUnknown *)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2);
170 IBaseFilter_Release(filter);
171 ref = IUnknown_Release(unk);
172 ok(!ref, "Got unexpected refcount %d.\n", ref);
173 ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
176 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
177 static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported)
179 IUnknown *iface = iface_ptr;
180 HRESULT hr, expected_hr;
181 IUnknown *unk;
183 expected_hr = supported ? S_OK : E_NOINTERFACE;
185 hr = IUnknown_QueryInterface(iface, iid, (void **)&unk);
186 ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x, expected %#x.\n", hr, expected_hr);
187 if (SUCCEEDED(hr))
188 IUnknown_Release(unk);
191 static void test_interfaces(void)
193 IBaseFilter *filter = create_evr();
194 ULONG ref;
196 todo_wine check_interface(filter, &IID_IAMFilterMiscFlags, TRUE);
197 check_interface(filter, &IID_IBaseFilter, TRUE);
198 check_interface(filter, &IID_IMediaFilter, TRUE);
199 check_interface(filter, &IID_IMediaPosition, TRUE);
200 check_interface(filter, &IID_IMediaSeeking, TRUE);
201 check_interface(filter, &IID_IPersist, TRUE);
202 check_interface(filter, &IID_IUnknown, TRUE);
204 check_interface(filter, &IID_IBasicAudio, FALSE);
205 check_interface(filter, &IID_IBasicVideo, FALSE);
206 check_interface(filter, &IID_IDirectXVideoMemoryConfiguration, FALSE);
207 check_interface(filter, &IID_IMemInputPin, FALSE);
208 check_interface(filter, &IID_IPersistPropertyBag, FALSE);
209 check_interface(filter, &IID_IPin, FALSE);
210 check_interface(filter, &IID_IReferenceClock, FALSE);
211 check_interface(filter, &IID_IVideoWindow, FALSE);
213 ref = IBaseFilter_Release(filter);
214 ok(!ref, "Got unexpected refcount %d.\n", ref);
217 static void test_enum_pins(void)
219 IBaseFilter *filter = create_evr();
220 IEnumPins *enum1, *enum2;
221 ULONG count, ref;
222 IPin *pins[2];
223 HRESULT hr;
225 ref = get_refcount(filter);
226 ok(ref == 1, "Got unexpected refcount %d.\n", ref);
228 hr = IBaseFilter_EnumPins(filter, NULL);
229 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
231 hr = IBaseFilter_EnumPins(filter, &enum1);
232 ok(hr == S_OK, "Got hr %#x.\n", hr);
233 ref = get_refcount(filter);
234 ok(ref == 2, "Got unexpected refcount %d.\n", ref);
235 ref = get_refcount(enum1);
236 ok(ref == 1, "Got unexpected refcount %d.\n", ref);
238 hr = IEnumPins_Next(enum1, 1, NULL, NULL);
239 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
241 hr = IEnumPins_Next(enum1, 1, pins, NULL);
242 ok(hr == S_OK, "Got hr %#x.\n", hr);
243 ref = get_refcount(filter);
244 ok(ref == 3, "Got unexpected refcount %d.\n", ref);
245 ref = get_refcount(pins[0]);
246 ok(ref == 3, "Got unexpected refcount %d.\n", ref);
247 ref = get_refcount(enum1);
248 ok(ref == 1, "Got unexpected refcount %d.\n", ref);
249 IPin_Release(pins[0]);
250 ref = get_refcount(filter);
251 ok(ref == 2, "Got unexpected refcount %d.\n", ref);
253 hr = IEnumPins_Next(enum1, 1, pins, NULL);
254 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
256 hr = IEnumPins_Reset(enum1);
257 ok(hr == S_OK, "Got hr %#x.\n", hr);
259 hr = IEnumPins_Next(enum1, 1, pins, &count);
260 ok(hr == S_OK, "Got hr %#x.\n", hr);
261 ok(count == 1, "Got count %u.\n", count);
262 IPin_Release(pins[0]);
264 hr = IEnumPins_Next(enum1, 1, pins, &count);
265 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
266 ok(!count, "Got count %u.\n", count);
268 hr = IEnumPins_Reset(enum1);
269 ok(hr == S_OK, "Got hr %#x.\n", hr);
271 hr = IEnumPins_Next(enum1, 2, pins, NULL);
272 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
274 hr = IEnumPins_Next(enum1, 2, pins, &count);
275 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
276 ok(count == 1, "Got count %u.\n", count);
277 IPin_Release(pins[0]);
279 hr = IEnumPins_Reset(enum1);
280 ok(hr == S_OK, "Got hr %#x.\n", hr);
282 hr = IEnumPins_Clone(enum1, &enum2);
283 ok(hr == S_OK, "Got hr %#x.\n", hr);
285 hr = IEnumPins_Skip(enum1, 2);
286 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
288 hr = IEnumPins_Skip(enum1, 1);
289 ok(hr == S_OK, "Got hr %#x.\n", hr);
291 hr = IEnumPins_Skip(enum1, 1);
292 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
294 hr = IEnumPins_Next(enum1, 1, pins, NULL);
295 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
297 hr = IEnumPins_Next(enum2, 1, pins, NULL);
298 ok(hr == S_OK, "Got hr %#x.\n", hr);
299 IPin_Release(pins[0]);
301 IEnumPins_Release(enum2);
302 IEnumPins_Release(enum1);
303 ref = IBaseFilter_Release(filter);
304 ok(!ref, "Got outstanding refcount %d.\n", ref);
307 static void test_find_pin(void)
309 IBaseFilter *filter = create_evr();
310 IEnumPins *enum_pins;
311 IPin *pin, *pin2;
312 HRESULT hr;
313 ULONG ref;
315 hr = IBaseFilter_EnumPins(filter, &enum_pins);
316 ok(hr == S_OK, "Got hr %#x.\n", hr);
318 hr = IBaseFilter_FindPin(filter, sink_id, &pin);
319 ok(hr == S_OK, "Got hr %#x.\n", hr);
320 hr = IEnumPins_Next(enum_pins, 1, &pin2, NULL);
321 ok(hr == S_OK, "Got hr %#x.\n", hr);
322 ok(pin2 == pin, "Expected pin %p, got %p.\n", pin, pin2);
323 IPin_Release(pin2);
324 IPin_Release(pin);
326 IEnumPins_Release(enum_pins);
327 ref = IBaseFilter_Release(filter);
328 ok(!ref, "Got outstanding refcount %d.\n", ref);
331 static void test_pin_info(void)
333 IBaseFilter *filter = create_evr();
334 PIN_DIRECTION dir;
335 PIN_INFO info;
336 HRESULT hr;
337 WCHAR *id;
338 ULONG ref;
339 IPin *pin;
341 hr = IBaseFilter_FindPin(filter, sink_id, &pin);
342 ok(hr == S_OK, "Got hr %#x.\n", hr);
343 ref = get_refcount(filter);
344 ok(ref == 2, "Got unexpected refcount %d.\n", ref);
345 ref = get_refcount(pin);
346 ok(ref == 2, "Got unexpected refcount %d.\n", ref);
348 hr = IPin_QueryPinInfo(pin, &info);
349 ok(hr == S_OK, "Got hr %#x.\n", hr);
350 ok(info.pFilter == filter, "Expected filter %p, got %p.\n", filter, info.pFilter);
351 ok(info.dir == PINDIR_INPUT, "Got direction %d.\n", info.dir);
352 ok(!lstrcmpW(info.achName, sink_id), "Got name %s.\n", wine_dbgstr_w(info.achName));
353 ref = get_refcount(filter);
354 ok(ref == 3, "Got unexpected refcount %d.\n", ref);
355 ref = get_refcount(pin);
356 ok(ref == 3, "Got unexpected refcount %d.\n", ref);
357 IBaseFilter_Release(info.pFilter);
359 hr = IPin_QueryDirection(pin, &dir);
360 ok(hr == S_OK, "Got hr %#x.\n", hr);
361 ok(dir == PINDIR_INPUT, "Got direction %d.\n", dir);
363 hr = IPin_QueryId(pin, &id);
364 ok(hr == S_OK, "Got hr %#x.\n", hr);
365 ok(!lstrcmpW(id, sink_id), "Got id %s.\n", wine_dbgstr_w(id));
366 CoTaskMemFree(id);
368 hr = IPin_QueryInternalConnections(pin, NULL, NULL);
369 ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
371 IPin_Release(pin);
372 ref = IBaseFilter_Release(filter);
373 ok(!ref, "Got outstanding refcount %d.\n", ref);
376 static void test_default_mixer(void)
378 DWORD input_min, input_max, output_min, output_max;
379 MFT_OUTPUT_STREAM_INFO output_info;
380 MFT_INPUT_STREAM_INFO input_info;
381 DWORD input_count, output_count;
382 IMFVideoDeviceID *deviceid;
383 DWORD input_id, output_id;
384 IMFAttributes *attributes, *attributes2;
385 IMFTransform *transform;
386 IMFGetService *gs;
387 unsigned int i;
388 DWORD ids[16];
389 IUnknown *unk;
390 HRESULT hr;
391 IID iid;
393 hr = MFCreateVideoMixer(NULL, &IID_IDirect3DDevice9, &IID_IMFTransform, (void **)&transform);
394 ok(hr == S_OK, "Failed to create default mixer, hr %#x.\n", hr);
396 hr = IMFTransform_QueryInterface(transform, &IID_IMFTopologyServiceLookupClient, (void **)&unk);
397 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
398 IUnknown_Release(unk);
400 hr = IMFTransform_QueryInterface(transform, &IID_IMFGetService, (void **)&gs);
401 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
403 hr = IMFGetService_GetService(gs, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoMixerBitmap, (void **)&unk);
404 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
405 IUnknown_Release(unk);
407 hr = IMFGetService_GetService(gs, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoProcessor, (void **)&unk);
408 todo_wine
409 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
410 if (SUCCEEDED(hr))
411 IUnknown_Release(unk);
413 hr = IMFGetService_GetService(gs, &MR_VIDEO_MIXER_SERVICE, &IID_IMFVideoPositionMapper, (void **)&unk);
414 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
415 IUnknown_Release(unk);
417 IMFGetService_Release(gs);
419 hr = IMFTransform_QueryInterface(transform, &IID_IMFVideoMixerBitmap, (void **)&unk);
420 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
421 IUnknown_Release(unk);
423 hr = IMFTransform_QueryInterface(transform, &IID_IMFVideoPositionMapper, (void **)&unk);
424 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
425 IUnknown_Release(unk);
427 hr = IMFTransform_QueryInterface(transform, &IID_IMFVideoProcessor, (void **)&unk);
428 todo_wine
429 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
430 if (SUCCEEDED(hr))
431 IUnknown_Release(unk);
433 hr = IMFTransform_QueryInterface(transform, &IID_IMFVideoMixerControl, (void **)&unk);
434 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
435 IUnknown_Release(unk);
437 hr = IMFTransform_QueryInterface(transform, &IID_IMFVideoDeviceID, (void **)&deviceid);
438 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
440 hr = IMFVideoDeviceID_GetDeviceID(deviceid, NULL);
441 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
443 hr = IMFVideoDeviceID_GetDeviceID(deviceid, &iid);
444 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
445 ok(IsEqualIID(&iid, &IID_IDirect3DDevice9), "Unexpected id %s.\n", wine_dbgstr_guid(&iid));
447 IMFVideoDeviceID_Release(deviceid);
449 /* Stream configuration. */
450 input_count = output_count = 0;
451 hr = IMFTransform_GetStreamCount(transform, &input_count, &output_count);
452 ok(hr == S_OK, "Failed to get stream count, hr %#x.\n", hr);
453 ok(input_count == 1 && output_count == 1, "Unexpected stream count %u/%u.\n", input_count, output_count);
455 hr = IMFTransform_GetStreamLimits(transform, &input_min, &input_max, &output_min, &output_max);
456 ok(hr == S_OK, "Failed to get stream limits, hr %#x.\n", hr);
457 ok(input_min == 1 && input_max == 16 && output_min == 1 && output_max == 1, "Unexpected stream limits %u/%u, %u/%u.\n",
458 input_min, input_max, output_min, output_max);
460 hr = IMFTransform_GetInputStreamInfo(transform, 1, &input_info);
461 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
463 hr = IMFTransform_GetOutputStreamInfo(transform, 1, &output_info);
464 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
466 memset(&input_info, 0xcc, sizeof(input_info));
467 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
468 ok(hr == S_OK, "Failed to get input info, hr %#x.\n", hr);
470 memset(&output_info, 0xcc, sizeof(output_info));
471 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
472 ok(hr == S_OK, "Failed to get input info, hr %#x.\n", hr);
473 ok(!(output_info.dwFlags & (MFT_OUTPUT_STREAM_PROVIDES_SAMPLES | MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES)),
474 "Unexpected output flags %#x.\n", output_info.dwFlags);
476 hr = IMFTransform_GetStreamIDs(transform, 1, &input_id, 1, &output_id);
477 ok(hr == S_OK, "Failed to get input info, hr %#x.\n", hr);
478 ok(input_id == 0 && output_id == 0, "Unexpected stream ids.\n");
480 hr = IMFTransform_GetInputStreamAttributes(transform, 1, &attributes);
481 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
483 hr = IMFTransform_GetOutputStreamAttributes(transform, 1, &attributes);
484 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
486 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &attributes);
487 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
489 hr = IMFTransform_AddInputStreams(transform, 16, NULL);
490 ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr);
492 hr = IMFTransform_AddInputStreams(transform, 16, ids);
493 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
495 memset(ids, 0, sizeof(ids));
496 hr = IMFTransform_AddInputStreams(transform, 15, ids);
497 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
499 for (i = 0; i < ARRAY_SIZE(ids); ++i)
500 ids[i] = i + 1;
502 hr = IMFTransform_AddInputStreams(transform, 15, ids);
503 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
505 input_count = output_count = 0;
506 hr = IMFTransform_GetStreamCount(transform, &input_count, &output_count);
507 ok(hr == S_OK, "Failed to get stream count, hr %#x.\n", hr);
508 ok(input_count == 16 && output_count == 1, "Unexpected stream count %u/%u.\n", input_count, output_count);
510 memset(&input_info, 0, sizeof(input_info));
511 hr = IMFTransform_GetInputStreamInfo(transform, 1, &input_info);
512 ok(hr == S_OK, "Failed to get input info, hr %#x.\n", hr);
513 ok((input_info.dwFlags & (MFT_INPUT_STREAM_REMOVABLE | MFT_INPUT_STREAM_OPTIONAL)) ==
514 (MFT_INPUT_STREAM_REMOVABLE | MFT_INPUT_STREAM_OPTIONAL), "Unexpected flags %#x.\n", input_info.dwFlags);
516 attributes = NULL;
517 hr = IMFTransform_GetInputStreamAttributes(transform, 0, &attributes);
518 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
519 ok(!!attributes, "Unexpected attributes.\n");
521 attributes2 = NULL;
522 hr = IMFTransform_GetInputStreamAttributes(transform, 0, &attributes2);
523 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
524 ok(attributes == attributes2, "Unexpected instance.\n");
526 IMFAttributes_Release(attributes2);
527 IMFAttributes_Release(attributes);
529 attributes = NULL;
530 hr = IMFTransform_GetInputStreamAttributes(transform, 1, &attributes);
531 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
532 ok(!!attributes, "Unexpected attributes.\n");
533 IMFAttributes_Release(attributes);
535 hr = IMFTransform_DeleteInputStream(transform, 0);
536 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#x.\n", hr);
538 hr = IMFTransform_DeleteInputStream(transform, 1);
539 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
541 input_count = output_count = 0;
542 hr = IMFTransform_GetStreamCount(transform, &input_count, &output_count);
543 ok(hr == S_OK, "Failed to get stream count, hr %#x.\n", hr);
544 ok(input_count == 15 && output_count == 1, "Unexpected stream count %u/%u.\n", input_count, output_count);
546 IMFTransform_Release(transform);
548 hr = MFCreateVideoMixer(NULL, &IID_IMFTransform, &IID_IMFTransform, (void **)&transform);
549 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
551 hr = CoCreateInstance(&CLSID_MFVideoMixer9, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)&transform);
552 ok(hr == S_OK, "Failed to create default mixer, hr %#x.\n", hr);
553 IMFTransform_Release(transform);
556 static void test_surface_sample(void)
558 IDirect3DSurface9 *backbuffer = NULL;
559 IMFMediaBuffer *buffer, *buffer2;
560 IDirect3DSwapChain9 *swapchain;
561 IDirect3DDevice9 *device;
562 DWORD count, length;
563 IMFSample *sample;
564 LONGLONG duration;
565 IDirect3D9 *d3d;
566 IUnknown *unk;
567 HWND window;
568 HRESULT hr;
569 BYTE *data;
571 window = create_window();
572 d3d = Direct3DCreate9(D3D_SDK_VERSION);
573 ok(!!d3d, "Failed to create a D3D object.\n");
574 if (!(device = create_device(d3d, window)))
576 skip("Failed to create a D3D device, skipping tests.\n");
577 goto done;
580 hr = IDirect3DDevice9_GetSwapChain(device, 0, &swapchain);
581 ok(SUCCEEDED(hr), "Failed to get the implicit swapchain (%08x)\n", hr);
583 hr = IDirect3DSwapChain9_GetBackBuffer(swapchain, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
584 ok(SUCCEEDED(hr), "Failed to get the back buffer (%08x)\n", hr);
585 ok(backbuffer != NULL, "The back buffer is NULL\n");
587 IDirect3DSwapChain9_Release(swapchain);
589 hr = MFCreateVideoSampleFromSurface((IUnknown *)backbuffer, &sample);
590 todo_wine
591 ok(hr == S_OK, "Failed to create surface sample, hr %#x.\n", hr);
592 if (FAILED(hr)) goto done;
594 hr = IMFSample_QueryInterface(sample, &IID_IMFTrackedSample, (void **)&unk);
595 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
596 IUnknown_Release(unk);
598 hr = IMFSample_QueryInterface(sample, &IID_IMFDesiredSample, (void **)&unk);
599 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
600 IUnknown_Release(unk);
602 hr = IMFSample_GetCount(sample, &count);
603 ok(hr == S_OK, "Failed to get attribute count, hr %#x.\n", hr);
604 ok(!count, "Unexpected attribute count.\n");
606 hr = IMFSample_GetBufferCount(sample, &count);
607 ok(hr == S_OK, "Failed to get buffer count, hr %#x.\n", hr);
608 ok(count == 1, "Unexpected attribute count.\n");
610 hr = IMFSample_GetTotalLength(sample, &length);
611 ok(hr == S_OK, "Failed to get length, hr %#x.\n", hr);
612 ok(!length, "Unexpected length %u.\n", length);
614 hr = IMFSample_GetSampleDuration(sample, &duration);
615 ok(hr == MF_E_NO_SAMPLE_DURATION, "Unexpected hr %#x.\n", hr);
617 hr = IMFSample_GetSampleTime(sample, &duration);
618 ok(hr == MF_E_NO_SAMPLE_TIMESTAMP, "Unexpected hr %#x.\n", hr);
620 hr = IMFSample_GetBufferByIndex(sample, 0, &buffer);
621 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
623 hr = IMFMediaBuffer_GetMaxLength(buffer, &length);
624 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
626 hr = IMFMediaBuffer_GetCurrentLength(buffer, &length);
627 ok(hr == S_OK, "Failed to get length, hr %#x.\n", hr);
628 ok(!length, "Unexpected length %u.\n", length);
630 hr = IMFMediaBuffer_Lock(buffer, &data, NULL, NULL);
631 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
633 hr = IMFMediaBuffer_QueryInterface(buffer, &IID_IMF2DBuffer, (void **)&unk);
634 ok(hr == E_NOINTERFACE, "Unexpected hr %#x.\n", hr);
636 hr = IMFSample_AddBuffer(sample, buffer);
637 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
639 hr = IMFSample_GetBufferCount(sample, &count);
640 ok(hr == S_OK, "Failed to get buffer count, hr %#x.\n", hr);
641 ok(count == 2, "Unexpected attribute count.\n");
643 hr = IMFSample_ConvertToContiguousBuffer(sample, &buffer2);
644 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
646 hr = IMFSample_CopyToBuffer(sample, buffer);
647 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
649 hr = IMFSample_RemoveAllBuffers(sample);
650 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
652 hr = IMFSample_GetBufferCount(sample, &count);
653 ok(hr == S_OK, "Failed to get buffer count, hr %#x.\n", hr);
654 ok(!count, "Unexpected attribute count.\n");
656 IMFMediaBuffer_Release(buffer);
658 IMFSample_Release(sample);
660 done:
661 if (backbuffer)
662 IDirect3DSurface9_Release(backbuffer);
663 IDirect3D9_Release(d3d);
664 DestroyWindow(window);
667 static void test_default_mixer_type_negotiation(void)
669 IDirect3DDeviceManager9 *manager;
670 IMFVideoMediaType *video_type;
671 IMFMediaType *media_type;
672 IDirect3DDevice9 *device;
673 IMFTransform *transform;
674 IDirect3D9 *d3d;
675 HWND window;
676 HRESULT hr;
677 UINT token;
679 if (!pMFCreateVideoMediaTypeFromSubtype)
681 win_skip("Skipping mixer types tests.\n");
682 return;
685 hr = MFCreateVideoMixer(NULL, &IID_IDirect3DDevice9, &IID_IMFTransform, (void **)&transform);
686 ok(hr == S_OK, "Failed to create default mixer, hr %#x.\n", hr);
688 hr = IMFTransform_GetInputAvailableType(transform, 0, 0, &media_type);
689 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
691 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type);
692 todo_wine
693 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#x.\n", hr);
695 hr = MFCreateMediaType(&media_type);
696 ok(hr == S_OK, "Failed to create media type, hr %#x.\n", hr);
698 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
699 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
701 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
702 ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr);
704 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
705 ok(hr == MF_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
707 /* Now try with device manager. */
709 window = create_window();
710 d3d = Direct3DCreate9(D3D_SDK_VERSION);
711 ok(!!d3d, "Failed to create a D3D object.\n");
712 if (!(device = create_device(d3d, window)))
714 skip("Failed to create a D3D device, skipping tests.\n");
715 goto done;
718 hr = DXVA2CreateDirect3DDeviceManager9(&token, &manager);
719 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
721 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_SET_D3D_MANAGER, (ULONG_PTR)manager);
722 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
724 /* Now manager is not initialized. */
725 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
726 ok(hr == DXVA2_E_NOT_INITIALIZED, "Unexpected hr %#x.\n", hr);
728 hr = IDirect3DDeviceManager9_ResetDevice(manager, device, token);
729 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
731 /* And now type description is incomplete. */
732 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
733 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
734 IMFMediaType_Release(media_type);
736 hr = pMFCreateVideoMediaTypeFromSubtype(&MFVideoFormat_RGB32, &video_type);
737 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
739 /* Partially initialized type. */
740 hr = IMFTransform_SetInputType(transform, 0, (IMFMediaType *)video_type, 0);
741 ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
743 /* Only required data - frame size and uncompressed marker. */
744 hr = IMFVideoMediaType_SetUINT64(video_type, &MF_MT_FRAME_SIZE, (UINT64)640 << 32 | 480);
745 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
746 hr = IMFVideoMediaType_SetUINT32(video_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE);
747 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
749 hr = IMFTransform_SetInputType(transform, 0, (IMFMediaType *)video_type, 0);
750 todo_wine
751 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
753 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type);
754 todo_wine
755 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
756 if (SUCCEEDED(hr))
758 ok(media_type != (IMFMediaType *)video_type, "Unexpected pointer.\n");
759 IMFMediaType_Release(media_type);
762 IMFVideoMediaType_Release(video_type);
764 IDirect3DDeviceManager9_Release(manager);
766 IDirect3DDevice9_Release(device);
768 done:
769 IMFTransform_Release(transform);
770 IDirect3D9_Release(d3d);
771 DestroyWindow(window);
774 START_TEST(evr)
776 CoInitialize(NULL);
778 pMFCreateVideoMediaTypeFromSubtype = (void *)GetProcAddress(GetModuleHandleA("mfplat.dll"), "MFCreateVideoMediaTypeFromSubtype");
780 test_aggregation();
781 test_interfaces();
782 test_enum_pins();
783 test_find_pin();
784 test_pin_info();
785 test_default_mixer();
786 test_default_mixer_type_negotiation();
787 test_surface_sample();
789 CoUninitialize();