1 /* 2 * Unit tests for Media Detector 3 * 4 * Copyright (C) 2008 Google (Lei Zhang, Dan Hipschman) 5 * 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. 10 * 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. 15 * 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 19 */ 20 21 #define COBJMACROS 22 #define CONST_VTABLE 23 24 #include "initguid.h" 25 #include "ole2.h" 26 #include "vfwmsgs.h" 27 #include "uuids.h" 28 #include "wine/test.h" 29 #include "qedit.h" 30 #include "control.h" 31 #include "rc.h" 32 33 /* Outer IUnknown for COM aggregation tests */ 34 struct unk_impl { 35 IUnknown IUnknown_iface; 36 LONG ref; 37 IUnknown *inner_unk; 38 }; 39 40 static inline struct unk_impl *impl_from_IUnknown(IUnknown *iface) 41 { 42 return CONTAINING_RECORD(iface, struct unk_impl, IUnknown_iface); 43 } 44 45 static HRESULT WINAPI unk_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) 46 { 47 struct unk_impl *This = impl_from_IUnknown(iface); 48 49 return IUnknown_QueryInterface(This->inner_unk, riid, ppv); 50 } 51 52 static ULONG WINAPI unk_AddRef(IUnknown *iface) 53 { 54 struct unk_impl *This = impl_from_IUnknown(iface); 55 56 return InterlockedIncrement(&This->ref); 57 } 58 59 static ULONG WINAPI unk_Release(IUnknown *iface) 60 { 61 struct unk_impl *This = impl_from_IUnknown(iface); 62 63 return InterlockedDecrement(&This->ref); 64 } 65 66 static const IUnknownVtbl unk_vtbl = 67 { 68 unk_QueryInterface, 69 unk_AddRef, 70 unk_Release 71 }; 72 73 74 static WCHAR test_avi_filename[MAX_PATH]; 75 static WCHAR test_sound_avi_filename[MAX_PATH]; 76 77 static BOOL unpack_avi_file(int id, WCHAR name[MAX_PATH]) 78 { 79 static WCHAR temp_path[MAX_PATH]; 80 static const WCHAR prefix[] = {'D','E','S',0}; 81 static const WCHAR avi[] = {'a','v','i',0}; 82 HRSRC res; 83 HGLOBAL data; 84 char *mem; 85 DWORD size, written; 86 HANDLE fh; 87 BOOL ret; 88 89 res = FindResourceW(NULL, MAKEINTRESOURCEW(id), MAKEINTRESOURCEW(AVI_RES_TYPE)); 90 if (!res) 91 return FALSE; 92 93 data = LoadResource(NULL, res); 94 if (!data) 95 return FALSE; 96 97 mem = LockResource(data); 98 if (!mem) 99 return FALSE; 100 101 size = SizeofResource(NULL, res); 102 if (size == 0) 103 return FALSE; 104 105 if (!GetTempPathW(MAX_PATH, temp_path)) 106 return FALSE; 107 108 /* We might end up relying on the extension here, so .TMP is no good. */ 109 if (!GetTempFileNameW(temp_path, prefix, 0, name)) 110 return FALSE; 111 112 DeleteFileW(name); 113 lstrcpyW(name + lstrlenW(name) - 3, avi); 114 115 fh = CreateFileW(name, GENERIC_WRITE, 0, NULL, CREATE_NEW, 116 FILE_ATTRIBUTE_NORMAL, NULL); 117 if (fh == INVALID_HANDLE_VALUE) 118 return FALSE; 119 120 ret = WriteFile(fh, mem, size, &written, NULL); 121 CloseHandle(fh); 122 return ret && written == size; 123 } 124 125 static BOOL init_tests(void) 126 { 127 return unpack_avi_file(TEST_AVI_RES, test_avi_filename) 128 && unpack_avi_file(TEST_SOUND_AVI_RES, test_sound_avi_filename); 129 } 130 131 static void test_mediadet(void) 132 { 133 HRESULT hr; 134 struct unk_impl unk_obj = {{&unk_vtbl}, 19, NULL}; 135 IMediaDet *pM = NULL; 136 ULONG refcount; 137 BSTR filename = NULL; 138 LONG nstrms = 0; 139 LONG strm; 140 AM_MEDIA_TYPE mt; 141 double fps; 142 int flags; 143 int i; 144 145 /* COM aggregation */ 146 hr = CoCreateInstance(&CLSID_MediaDet, &unk_obj.IUnknown_iface, CLSCTX_INPROC_SERVER, 147 &IID_IUnknown, (void**)&unk_obj.inner_unk); 148 ok(hr == S_OK, "CoCreateInstance failed: %08x\n", hr); 149 150 hr = IUnknown_QueryInterface(unk_obj.inner_unk, &IID_IMediaDet, (void**)&pM); 151 ok(hr == S_OK, "QueryInterface for IID_IMediaDet failed: %08x\n", hr); 152 refcount = IMediaDet_AddRef(pM); 153 ok(refcount == unk_obj.ref, "MediaDet just pretends to support COM aggregation\n"); 154 refcount = IMediaDet_Release(pM); 155 ok(refcount == unk_obj.ref, "MediaDet just pretends to support COM aggregation\n"); 156 refcount = IMediaDet_Release(pM); 157 ok(refcount == 19, "Refcount should be back at 19 but is %u\n", refcount); 158 159 IUnknown_Release(unk_obj.inner_unk); 160 161 /* test.avi has one video stream. */ 162 hr = CoCreateInstance(&CLSID_MediaDet, NULL, CLSCTX_INPROC_SERVER, 163 &IID_IMediaDet, (LPVOID*)&pM); 164 ok(hr == S_OK, "CoCreateInstance failed with %x\n", hr); 165 ok(pM != NULL, "pM is NULL\n"); 166 167 filename = NULL; 168 hr = IMediaDet_get_Filename(pM, &filename); 169 /* Despite what MSDN claims, this returns S_OK. */ 170 ok(hr == S_OK, "IMediaDet_get_Filename failed: %08x\n", hr); 171 ok(filename == NULL, "IMediaDet_get_Filename\n"); 172 173 filename = (BSTR) -1; 174 hr = IMediaDet_get_Filename(pM, &filename); 175 /* Despite what MSDN claims, this returns S_OK. */ 176 ok(hr == S_OK, "IMediaDet_get_Filename failed: %08x\n", hr); 177 ok(filename == NULL, "IMediaDet_get_Filename\n"); 178 179 nstrms = -1; 180 hr = IMediaDet_get_OutputStreams(pM, &nstrms); 181 ok(hr == E_INVALIDARG, "IMediaDet_get_OutputStreams failed: %08x\n", hr); 182 ok(nstrms == -1, "IMediaDet_get_OutputStreams: nstrms is %i\n", nstrms); 183 184 strm = -1; 185 /* The stream defaults to 0, even without a file! */ 186 hr = IMediaDet_get_CurrentStream(pM, &strm); 187 ok(hr == S_OK, "IMediaDet_get_CurrentStream failed: %08x\n", hr); 188 ok(strm == 0, "IMediaDet_get_CurrentStream: strm is %i\n", strm); 189 190 hr = IMediaDet_get_CurrentStream(pM, NULL); 191 ok(hr == E_POINTER, "IMediaDet_get_CurrentStream failed: %08x\n", hr); 192 193 /* But put_CurrentStream doesn't. */ 194 hr = IMediaDet_put_CurrentStream(pM, 0); 195 ok(hr == E_INVALIDARG, "IMediaDet_put_CurrentStream failed: %08x\n", hr); 196 197 hr = IMediaDet_put_CurrentStream(pM, -1); 198 ok(hr == E_INVALIDARG, "IMediaDet_put_CurrentStream failed: %08x\n", hr); 199 200 hr = IMediaDet_get_StreamMediaType(pM, &mt); 201 ok(hr == E_INVALIDARG, "IMediaDet_get_StreamMediaType failed: %08x\n", hr); 202 203 hr = IMediaDet_get_StreamMediaType(pM, NULL); 204 ok(hr == E_POINTER, "IMediaDet_get_StreamMediaType failed: %08x\n", hr); 205 206 filename = SysAllocString(test_avi_filename); 207 hr = IMediaDet_put_Filename(pM, filename); 208 ok(hr == S_OK, "IMediaDet_put_Filename failed: %08x\n", hr); 209 SysFreeString(filename); 210 211 strm = -1; 212 /* The stream defaults to 0. */ 213 hr = IMediaDet_get_CurrentStream(pM, &strm); 214 ok(hr == S_OK, "IMediaDet_get_CurrentStream failed: %08x\n", hr); 215 ok(strm == 0, "IMediaDet_get_CurrentStream: strm is %i\n", strm); 216 217 ZeroMemory(&mt, sizeof mt); 218 hr = IMediaDet_get_StreamMediaType(pM, &mt); 219 ok(hr == S_OK, "IMediaDet_get_StreamMediaType failed: %08x\n", hr); 220 CoTaskMemFree(mt.pbFormat); 221 222 /* Even before get_OutputStreams. */ 223 hr = IMediaDet_put_CurrentStream(pM, 1); 224 ok(hr == E_INVALIDARG, "IMediaDet_put_CurrentStream failed: %08x\n", hr); 225 226 hr = IMediaDet_get_OutputStreams(pM, &nstrms); 227 ok(hr == S_OK, "IMediaDet_get_OutputStreams failed: %08x\n", hr); 228 ok(nstrms == 1, "IMediaDet_get_OutputStreams: nstrms is %i\n", nstrms); 229 230 filename = NULL; 231 hr = IMediaDet_get_Filename(pM, &filename); 232 ok(hr == S_OK, "IMediaDet_get_Filename failed: %08x\n", hr); 233 ok(lstrcmpW(filename, test_avi_filename) == 0, 234 "IMediaDet_get_Filename\n"); 235 SysFreeString(filename); 236 237 hr = IMediaDet_get_Filename(pM, NULL); 238 ok(hr == E_POINTER, "IMediaDet_get_Filename failed: %08x\n", hr); 239 240 strm = -1; 241 hr = IMediaDet_get_CurrentStream(pM, &strm); 242 ok(hr == S_OK, "IMediaDet_get_CurrentStream failed: %08x\n", hr); 243 ok(strm == 0, "IMediaDet_get_CurrentStream: strm is %i\n", strm); 244 245 hr = IMediaDet_get_CurrentStream(pM, NULL); 246 ok(hr == E_POINTER, "IMediaDet_get_CurrentStream failed: %08x\n", hr); 247 248 hr = IMediaDet_put_CurrentStream(pM, -1); 249 ok(hr == E_INVALIDARG, "IMediaDet_put_CurrentStream failed: %08x\n", hr); 250 251 hr = IMediaDet_put_CurrentStream(pM, 1); 252 ok(hr == E_INVALIDARG, "IMediaDet_put_CurrentStream failed: %08x\n", hr); 253 254 /* Try again. */ 255 strm = -1; 256 hr = IMediaDet_get_CurrentStream(pM, &strm); 257 ok(hr == S_OK, "IMediaDet_get_CurrentStream failed: %08x\n", hr); 258 ok(strm == 0, "IMediaDet_get_CurrentStream: strm is %i\n", strm); 259 260 hr = IMediaDet_put_CurrentStream(pM, 0); 261 ok(hr == S_OK, "IMediaDet_put_CurrentStream failed: %08x\n", hr); 262 263 strm = -1; 264 hr = IMediaDet_get_CurrentStream(pM, &strm); 265 ok(hr == S_OK, "IMediaDet_get_CurrentStream failed: %08x\n", hr); 266 ok(strm == 0, "IMediaDet_get_CurrentStream: strm is %i\n", strm); 267 268 ZeroMemory(&mt, sizeof mt); 269 hr = IMediaDet_get_StreamMediaType(pM, &mt); 270 ok(hr == S_OK, "IMediaDet_get_StreamMediaType failed: %08x\n", hr); 271 ok(IsEqualGUID(&mt.majortype, &MEDIATYPE_Video), 272 "IMediaDet_get_StreamMediaType\n"); 273 CoTaskMemFree(mt.pbFormat); 274 275 hr = IMediaDet_get_FrameRate(pM, NULL); 276 ok(hr == E_POINTER, "IMediaDet_get_FrameRate failed: %08x\n", hr); 277 278 hr = IMediaDet_get_FrameRate(pM, &fps); 279 ok(hr == S_OK, "IMediaDet_get_FrameRate failed: %08x\n", hr); 280 ok(fps == 10.0, "IMediaDet_get_FrameRate: fps is %f\n", fps); 281 282 hr = IMediaDet_Release(pM); 283 ok(hr == 0, "IMediaDet_Release returned: %x\n", hr); 284 285 DeleteFileW(test_avi_filename); 286 287 /* test_sound.avi has one video stream and one audio stream. */ 288 hr = CoCreateInstance(&CLSID_MediaDet, NULL, CLSCTX_INPROC_SERVER, 289 &IID_IMediaDet, (LPVOID*)&pM); 290 ok(hr == S_OK, "CoCreateInstance failed with %x\n", hr); 291 ok(pM != NULL, "pM is NULL\n"); 292 293 filename = SysAllocString(test_sound_avi_filename); 294 hr = IMediaDet_put_Filename(pM, filename); 295 ok(hr == S_OK, "IMediaDet_put_Filename failed: %08x\n", hr); 296 SysFreeString(filename); 297 298 hr = IMediaDet_get_OutputStreams(pM, &nstrms); 299 ok(hr == S_OK, "IMediaDet_get_OutputStreams failed: %08x\n", hr); 300 ok(nstrms == 2, "IMediaDet_get_OutputStreams: nstrms is %i\n", nstrms); 301 302 filename = NULL; 303 hr = IMediaDet_get_Filename(pM, &filename); 304 ok(hr == S_OK, "IMediaDet_get_Filename failed: %08x\n", hr); 305 ok(lstrcmpW(filename, test_sound_avi_filename) == 0, 306 "IMediaDet_get_Filename\n"); 307 SysFreeString(filename); 308 309 /* I don't know if the stream order is deterministic. Just check 310 for both an audio and video stream. */ 311 flags = 0; 312 313 for (i = 0; i < 2; ++i) 314 { 315 hr = IMediaDet_put_CurrentStream(pM, i); 316 ok(hr == S_OK, "IMediaDet_put_CurrentStream failed: %08x\n", hr); 317 318 strm = -1; 319 hr = IMediaDet_get_CurrentStream(pM, &strm); 320 ok(hr == S_OK, "IMediaDet_get_CurrentStream failed: %08x\n", hr); 321 ok(strm == i, "IMediaDet_get_CurrentStream: strm is %i\n", strm); 322 323 ZeroMemory(&mt, sizeof mt); 324 hr = IMediaDet_get_StreamMediaType(pM, &mt); 325 ok(hr == S_OK, "IMediaDet_get_StreamMediaType failed: %08x\n", hr); 326 flags += (IsEqualGUID(&mt.majortype, &MEDIATYPE_Video) 327 ? 1 328 : (IsEqualGUID(&mt.majortype, &MEDIATYPE_Audio) 329 ? 2 330 : 0)); 331 332 if (IsEqualGUID(&mt.majortype, &MEDIATYPE_Audio)) 333 { 334 hr = IMediaDet_get_FrameRate(pM, &fps); 335 ok(hr == VFW_E_INVALIDMEDIATYPE, "IMediaDet_get_FrameRate failed: %08x\n", hr); 336 } 337 338 CoTaskMemFree(mt.pbFormat); 339 } 340 ok(flags == 3, "IMediaDet_get_StreamMediaType: flags are %i\n", flags); 341 342 hr = IMediaDet_put_CurrentStream(pM, 2); 343 ok(hr == E_INVALIDARG, "IMediaDet_put_CurrentStream failed: %08x\n", hr); 344 345 strm = -1; 346 hr = IMediaDet_get_CurrentStream(pM, &strm); 347 ok(hr == S_OK, "IMediaDet_get_CurrentStream failed: %08x\n", hr); 348 ok(strm == 1, "IMediaDet_get_CurrentStream: strm is %i\n", strm); 349 350 hr = IMediaDet_Release(pM); 351 ok(hr == 0, "IMediaDet_Release returned: %x\n", hr); 352 353 DeleteFileW(test_sound_avi_filename); 354 } 355 356 static HRESULT WINAPI ms_QueryInterface(IMediaSample *iface, REFIID riid, 357 void **ppvObject) 358 { 359 return E_NOTIMPL; 360 } 361 362 static ULONG WINAPI ms_AddRef(IMediaSample *iface) 363 { 364 return 2; 365 } 366 367 static ULONG WINAPI ms_Release(IMediaSample *iface) 368 { 369 return 1; 370 } 371 372 static HRESULT WINAPI ms_GetPointer(IMediaSample *iface, BYTE **ppBuffer) 373 { 374 return E_NOTIMPL; 375 } 376 377 static LONG WINAPI ms_GetSize(IMediaSample *iface) 378 { 379 return E_NOTIMPL; 380 } 381 382 static HRESULT WINAPI ms_GetTime(IMediaSample *iface, REFERENCE_TIME *pTimeStart, 383 REFERENCE_TIME *pTimeEnd) 384 { 385 return E_NOTIMPL; 386 } 387 388 static HRESULT WINAPI ms_SetTime(IMediaSample *iface, REFERENCE_TIME *pTimeStart, 389 REFERENCE_TIME *pTimeEnd) 390 { 391 return E_NOTIMPL; 392 } 393 394 static HRESULT WINAPI ms_IsSyncPoint(IMediaSample *iface) 395 { 396 return E_NOTIMPL; 397 } 398 399 static HRESULT WINAPI ms_SetSyncPoint(IMediaSample *iface, BOOL bIsSyncPoint) 400 { 401 return E_NOTIMPL; 402 } 403 404 static HRESULT WINAPI ms_IsPreroll(IMediaSample *iface) 405 { 406 return E_NOTIMPL; 407 } 408 409 static HRESULT WINAPI ms_SetPreroll(IMediaSample *iface, BOOL bIsPreroll) 410 { 411 return E_NOTIMPL; 412 } 413 414 static LONG WINAPI ms_GetActualDataLength(IMediaSample *iface) 415 { 416 return E_NOTIMPL; 417 } 418 419 static HRESULT WINAPI ms_SetActualDataLength(IMediaSample *iface, LONG length) 420 { 421 return E_NOTIMPL; 422 } 423 424 static HRESULT WINAPI ms_GetMediaType(IMediaSample *iface, AM_MEDIA_TYPE 425 **ppMediaType) 426 { 427 return E_NOTIMPL; 428 } 429 430 static HRESULT WINAPI ms_SetMediaType(IMediaSample *iface, AM_MEDIA_TYPE *pMediaType) 431 { 432 return E_NOTIMPL; 433 } 434 435 static HRESULT WINAPI ms_IsDiscontinuity(IMediaSample *iface) 436 { 437 return E_NOTIMPL; 438 } 439 440 static HRESULT WINAPI ms_SetDiscontinuity(IMediaSample *iface, BOOL bDiscontinuity) 441 { 442 return E_NOTIMPL; 443 } 444 445 static HRESULT WINAPI ms_GetMediaTime(IMediaSample *iface, LONGLONG *pTimeStart, 446 LONGLONG *pTimeEnd) 447 { 448 return E_NOTIMPL; 449 } 450 451 static HRESULT WINAPI ms_SetMediaTime(IMediaSample *iface, LONGLONG *pTimeStart, 452 LONGLONG *pTimeEnd) 453 { 454 return E_NOTIMPL; 455 } 456 457 static const IMediaSampleVtbl my_sample_vt = { 458 ms_QueryInterface, 459 ms_AddRef, 460 ms_Release, 461 ms_GetPointer, 462 ms_GetSize, 463 ms_GetTime, 464 ms_SetTime, 465 ms_IsSyncPoint, 466 ms_SetSyncPoint, 467 ms_IsPreroll, 468 ms_SetPreroll, 469 ms_GetActualDataLength, 470 ms_SetActualDataLength, 471 ms_GetMediaType, 472 ms_SetMediaType, 473 ms_IsDiscontinuity, 474 ms_SetDiscontinuity, 475 ms_GetMediaTime, 476 ms_SetMediaTime 477 }; 478 479 static IMediaSample my_sample = { &my_sample_vt }; 480 481 static BOOL samplecb_called = FALSE; 482 483 static HRESULT WINAPI sgcb_QueryInterface(ISampleGrabberCB *iface, REFIID riid, 484 void **ppvObject) 485 { 486 return E_NOTIMPL; 487 } 488 489 static ULONG WINAPI sgcb_AddRef(ISampleGrabberCB *iface) 490 { 491 return E_NOTIMPL; 492 } 493 494 static ULONG WINAPI sgcb_Release(ISampleGrabberCB *iface) 495 { 496 return E_NOTIMPL; 497 } 498 499 static HRESULT WINAPI sgcb_SampleCB(ISampleGrabberCB *iface, double SampleTime, 500 IMediaSample *pSample) 501 { 502 ok(pSample == &my_sample, "Got wrong IMediaSample: %p, expected %p\n", pSample, &my_sample); 503 samplecb_called = TRUE; 504 return E_NOTIMPL; 505 } 506 507 static HRESULT WINAPI sgcb_BufferCB(ISampleGrabberCB *iface, double SampleTime, 508 BYTE *pBuffer, LONG BufferLen) 509 { 510 ok(0, "BufferCB should not have been called\n"); 511 return E_NOTIMPL; 512 } 513 514 static const ISampleGrabberCBVtbl sgcb_vt = { 515 sgcb_QueryInterface, 516 sgcb_AddRef, 517 sgcb_Release, 518 sgcb_SampleCB, 519 sgcb_BufferCB 520 }; 521 522 static ISampleGrabberCB my_sg_cb = { &sgcb_vt }; 523 524 static void test_samplegrabber(void) 525 { 526 struct unk_impl unk_obj = {{&unk_vtbl}, 19, NULL}; 527 ISampleGrabber *sg; 528 IBaseFilter *bf; 529 IMediaFilter *mf; 530 IPersist *persist; 531 IUnknown *unk; 532 IPin *pin; 533 IMemInputPin *inpin; 534 IEnumPins *pins; 535 ULONG refcount; 536 HRESULT hr; 537 FILTER_STATE fstate; 538 539 /* COM aggregation */ 540 hr = CoCreateInstance(&CLSID_SampleGrabber, &unk_obj.IUnknown_iface, CLSCTX_INPROC_SERVER, 541 &IID_IUnknown, (void**)&unk_obj.inner_unk); 542 ok(hr == S_OK, "CoCreateInstance failed: %08x\n", hr); 543 544 hr = IUnknown_QueryInterface(unk_obj.inner_unk, &IID_ISampleGrabber, (void**)&sg); 545 ok(hr == S_OK, "QueryInterface for IID_ISampleGrabber failed: %08x\n", hr); 546 refcount = ISampleGrabber_AddRef(sg); 547 ok(refcount == unk_obj.ref, "SampleGrabber just pretends to support COM aggregation\n"); 548 refcount = ISampleGrabber_Release(sg); 549 ok(refcount == unk_obj.ref, "SampleGrabber just pretends to support COM aggregation\n"); 550 refcount = ISampleGrabber_Release(sg); 551 ok(refcount == 19, "Refcount should be back at 19 but is %u\n", refcount); 552 IUnknown_Release(unk_obj.inner_unk); 553 554 /* Invalid RIID */ 555 hr = CoCreateInstance(&CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, &IID_IClassFactory, 556 (void**)&sg); 557 ok(hr == E_NOINTERFACE, "SampleGrabber create failed: %08x, expected E_NOINTERFACE\n", hr); 558 559 /* Same refcount for all SampleGrabber interfaces */ 560 hr = CoCreateInstance(&CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, &IID_ISampleGrabber, 561 (void**)&sg); 562 ok(hr == S_OK, "SampleGrabber create failed: %08x, expected S_OK\n", hr); 563 refcount = ISampleGrabber_AddRef(sg); 564 ok(refcount == 2, "refcount == %u, expected 2\n", refcount); 565 566 hr = ISampleGrabber_QueryInterface(sg, &IID_IBaseFilter, (void**)&bf); 567 ok(hr == S_OK, "QueryInterface for IID_IBaseFilter failed: %08x\n", hr); 568 refcount = IBaseFilter_AddRef(bf); 569 ok(refcount == 4, "refcount == %u, expected 4\n", refcount); 570 refcount = IBaseFilter_Release(bf); 571 572 hr = ISampleGrabber_QueryInterface(sg, &IID_IMediaFilter, (void**)&mf); 573 ok(hr == S_OK, "QueryInterface for IID_IMediaFilter failed: %08x\n", hr); 574 refcount = IMediaFilter_AddRef(mf); 575 ok(refcount == 5, "refcount == %u, expected 5\n", refcount); 576 refcount = IMediaFilter_Release(mf); 577 578 hr = ISampleGrabber_QueryInterface(sg, &IID_IPersist, (void**)&persist); 579 ok(hr == S_OK, "QueryInterface for IID_IPersist failed: %08x\n", hr); 580 refcount = IPersist_AddRef(persist); 581 ok(refcount == 6, "refcount == %u, expected 6\n", refcount); 582 refcount = IPersist_Release(persist); 583 584 hr = ISampleGrabber_QueryInterface(sg, &IID_IUnknown, (void**)&unk); 585 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr); 586 refcount = IUnknown_AddRef(unk); 587 ok(refcount == 7, "refcount == %u, expected 7\n", refcount); 588 refcount = IUnknown_Release(unk); 589 590 hr = ISampleGrabber_SetCallback(sg, &my_sg_cb, 0); 591 ok(hr == S_OK, "SetCallback failed: %08x\n", hr); 592 593 hr = IBaseFilter_GetState(bf, 100, &fstate); 594 ok(hr == S_OK, "Failed to get filter state: %08x\n", hr); 595 ok(fstate == State_Stopped, "Got wrong filter state: %u\n", fstate); 596 597 hr = IBaseFilter_EnumPins(bf, &pins); 598 ok(hr == S_OK, "EnumPins create failed: %08x, expected S_OK\n", hr); 599 600 hr = IEnumPins_Next(pins, 1, &pin, NULL); 601 ok(hr == S_OK, "Next failed: %08x\n", hr); 602 603 IEnumPins_Release(pins); 604 605 hr = IPin_QueryInterface(pin, &IID_IMemInputPin, (void**)&inpin); 606 ok(hr == S_OK, "QueryInterface(IMemInputPin) failed: %08x\n", hr); 607 608 hr = IMemInputPin_Receive(inpin, &my_sample); 609 ok(hr == S_OK, "Receive failed: %08x\n", hr); 610 ok(samplecb_called == TRUE, "SampleCB should have been called\n"); 611 612 IMemInputPin_Release(inpin); 613 IPin_Release(pin); 614 615 /* Interfaces that native does not support */ 616 hr = ISampleGrabber_QueryInterface(sg, &IID_IMediaPosition, (void**)&unk); 617 todo_wine ok(hr == E_NOINTERFACE, "QueryInterface for IID_IMediaPosition failed: %08x\n", hr); 618 hr = ISampleGrabber_QueryInterface(sg, &IID_IMediaSeeking, (void**)&unk); 619 todo_wine ok(hr == E_NOINTERFACE, "QueryInterface for IID_IMediaSeeking failed: %08x\n", hr); 620 hr = ISampleGrabber_QueryInterface(sg, &IID_IMemInputPin, (void**)&unk); 621 ok(hr == E_NOINTERFACE, "QueryInterface for IID_IMemInputPin failed: %08x\n", hr); 622 hr = ISampleGrabber_QueryInterface(sg, &IID_IQualityControl, (void**)&unk); 623 ok(hr == E_NOINTERFACE, "QueryInterface for IID_IQualityControl failed: %08x\n", hr); 624 hr = ISampleGrabber_QueryInterface(sg, &IID_ISeekingPassThru, (void**)&unk); 625 ok(hr == E_NOINTERFACE, "QueryInterface for IID_ISeekingPassThru failed: %08x\n", hr); 626 627 while (ISampleGrabber_Release(sg)); 628 } 629 630 static void test_COM_sg_enumpins(void) 631 { 632 IBaseFilter *bf; 633 IEnumPins *pins, *pins2; 634 IUnknown *unk; 635 ULONG refcount; 636 HRESULT hr; 637 638 hr = CoCreateInstance(&CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, 639 (void**)&bf); 640 ok(hr == S_OK, "SampleGrabber create failed: %08x, expected S_OK\n", hr); 641 hr = IBaseFilter_EnumPins(bf, &pins); 642 ok(hr == S_OK, "EnumPins create failed: %08x, expected S_OK\n", hr); 643 644 /* Same refcount for all EnumPins interfaces */ 645 refcount = IEnumPins_AddRef(pins); 646 ok(refcount == 2, "refcount == %u, expected 2\n", refcount); 647 hr = IEnumPins_QueryInterface(pins, &IID_IEnumPins, (void**)&pins2); 648 ok(hr == S_OK, "QueryInterface for IID_IEnumPins failed: %08x\n", hr); 649 ok(pins == pins2, "QueryInterface for self failed (%p != %p)\n", pins, pins2); 650 IEnumPins_Release(pins2); 651 652 hr = IEnumPins_QueryInterface(pins, &IID_IUnknown, (void**)&unk); 653 ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr); 654 refcount = IUnknown_AddRef(unk); 655 ok(refcount == 4, "refcount == %u, expected 4\n", refcount); 656 refcount = IUnknown_Release(unk); 657 658 while (IEnumPins_Release(pins)); 659 IBaseFilter_Release(bf); 660 } 661 662 START_TEST(mediadet) 663 { 664 if (!init_tests()) 665 { 666 skip("Couldn't initialize tests!\n"); 667 return; 668 } 669 670 CoInitialize(NULL); 671 test_mediadet(); 672 test_samplegrabber(); 673 test_COM_sg_enumpins(); 674 CoUninitialize(); 675 } 676