static BOOL pin_matches(IPin *pin, PIN_DIRECTION direction, const GUID *cat, const GUID *type, BOOL unconnected) { IPin *partner; PIN_DIRECTION pindir; IPin_QueryDirection(pin, &pindir); if (pindir != direction) { TRACE("No match, wrong direction\n"); return FALSE; } if (unconnected && IPin_ConnectedTo(pin, &partner) == S_OK) { IPin_Release(partner); TRACE("No match, %p already connected to %p\n", pin, partner); return FALSE; } if (cat || type) FIXME("Ignoring category/type\n"); TRACE("Match made in heaven\n"); return TRUE; }
static HRESULT WINAPI IAMMultiMediaStreamImpl_OpenFile(IAMMultiMediaStream* iface, LPCWSTR filename, DWORD flags) { IAMMultiMediaStreamImpl *This = impl_from_IAMMultiMediaStream(iface); HRESULT ret = S_OK; IBaseFilter *BaseFilter = NULL; IEnumPins *EnumPins = NULL; IPin *ipin; PIN_DIRECTION pin_direction; const WCHAR sourceW[] = {'S','o','u','r','c','e',0}; TRACE("(%p/%p)->(%s,%x)\n", This, iface, debugstr_w(filename), flags); if (!filename) return E_POINTER; /* If Initialize was not called before, we do it here */ if (!This->pFilterGraph) ret = IAMMultiMediaStream_Initialize(iface, STREAMTYPE_READ, 0, NULL); if (SUCCEEDED(ret)) ret = IGraphBuilder_AddSourceFilter(This->pFilterGraph, filename, sourceW, &BaseFilter); if (SUCCEEDED(ret)) ret = IBaseFilter_EnumPins(BaseFilter, &EnumPins); if (SUCCEEDED(ret)) ret = IEnumPins_Next(EnumPins, 1, &ipin, NULL); if (SUCCEEDED(ret)) { ret = IPin_QueryDirection(ipin, &pin_direction); if (ret == S_OK && pin_direction == PINDIR_OUTPUT) This->ipin = ipin; } if (SUCCEEDED(ret) && !(flags & AMMSF_NORENDER)) ret = IGraphBuilder_Render(This->pFilterGraph, This->ipin); if (EnumPins) IEnumPins_Release(EnumPins); if (BaseFilter) IBaseFilter_Release(BaseFilter); return ret; }
static HRESULT WINAPI MediaDet_get_OutputStreams(IMediaDet* iface, LONG *pVal) { MediaDetImpl *This = impl_from_IMediaDet(iface); IEnumPins *pins; IPin *pin; HRESULT hr; TRACE("(%p)\n", This); if (!This->splitter) return E_INVALIDARG; if (This->num_streams != -1) { *pVal = This->num_streams; return S_OK; } *pVal = 0; hr = IBaseFilter_EnumPins(This->splitter, &pins); if (FAILED(hr)) return hr; while (IEnumPins_Next(pins, 1, &pin, NULL) == S_OK) { PIN_DIRECTION dir; hr = IPin_QueryDirection(pin, &dir); IPin_Release(pin); if (FAILED(hr)) { IEnumPins_Release(pins); return hr; } if (dir == PINDIR_OUTPUT) ++*pVal; } IEnumPins_Release(pins); This->num_streams = *pVal; return S_OK; }
static HRESULT SetCurPin(MediaDetImpl *This, LONG strm) { IEnumPins *pins; IPin *pin; HRESULT hr; assert(This->splitter); assert(0 <= strm && strm < This->num_streams); if (This->cur_pin) { IPin_Release(This->cur_pin); This->cur_pin = NULL; } hr = IBaseFilter_EnumPins(This->splitter, &pins); if (FAILED(hr)) return hr; while (IEnumPins_Next(pins, 1, &pin, NULL) == S_OK && !This->cur_pin) { PIN_DIRECTION dir; hr = IPin_QueryDirection(pin, &dir); if (FAILED(hr)) { IPin_Release(pin); IEnumPins_Release(pins); return hr; } if (dir == PINDIR_OUTPUT && strm-- == 0) This->cur_pin = pin; else IPin_Release(pin); } IEnumPins_Release(pins); assert(This->cur_pin); return S_OK; }
static HRESULT WINAPI DSoundRender_InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) { BaseInputPin *This = (BaseInputPin *)iface; PIN_DIRECTION pindirReceive; DSoundRenderImpl *DSImpl; HRESULT hr = S_OK; TRACE("(%p)->(%p, %p)\n", This, pReceivePin, pmt); dump_AM_MEDIA_TYPE(pmt); EnterCriticalSection(This->pin.pCritSec); { DSImpl = (DSoundRenderImpl*)This->pin.pinInfo.pFilter; DSImpl->rtLastStop = -1; if (This->pin.pConnectedTo) hr = VFW_E_ALREADY_CONNECTED; if (SUCCEEDED(hr) && This->pin.pFuncsTable->pfnCheckMediaType((BasePin*)This, pmt) != S_OK) hr = VFW_E_TYPE_NOT_ACCEPTED; if (SUCCEEDED(hr)) { IPin_QueryDirection(pReceivePin, &pindirReceive); if (pindirReceive != PINDIR_OUTPUT) { ERR("Can't connect from non-output pin\n"); hr = VFW_E_INVALID_DIRECTION; } } if (SUCCEEDED(hr)) { WAVEFORMATEX *format; DSBUFFERDESC buf_desc; TRACE("MajorType %s\n", debugstr_guid(&pmt->majortype)); TRACE("SubType %s\n", debugstr_guid(&pmt->subtype)); TRACE("Format %s\n", debugstr_guid(&pmt->formattype)); TRACE("Size %d\n", pmt->cbFormat); format = (WAVEFORMATEX*)pmt->pbFormat; DSImpl->buf_size = format->nAvgBytesPerSec; memset(&buf_desc,0,sizeof(DSBUFFERDESC)); buf_desc.dwSize = sizeof(DSBUFFERDESC); buf_desc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN | DSBCAPS_CTRLFREQUENCY | DSBCAPS_GETCURRENTPOSITION2; buf_desc.dwBufferBytes = DSImpl->buf_size; buf_desc.lpwfxFormat = format; hr = IDirectSound_CreateSoundBuffer(DSImpl->dsound, &buf_desc, &DSImpl->dsbuffer, NULL); if (FAILED(hr)) ERR("Can't create sound buffer (%x)\n", hr); } if (SUCCEEDED(hr)) { hr = IDirectSoundBuffer_SetVolume(DSImpl->dsbuffer, DSImpl->volume); if (FAILED(hr)) ERR("Can't set volume to %d (%x)\n", DSImpl->volume, hr); hr = IDirectSoundBuffer_SetPan(DSImpl->dsbuffer, DSImpl->pan); if (FAILED(hr)) ERR("Can't set pan to %d (%x)\n", DSImpl->pan, hr); DSImpl->write_pos = 0; hr = S_OK; } if (SUCCEEDED(hr)) { CopyMediaType(&This->pin.mtCurrent, pmt); This->pin.pConnectedTo = pReceivePin; IPin_AddRef(pReceivePin); } else if (hr != VFW_E_ALREADY_CONNECTED) { if (DSImpl->dsbuffer) IDirectSoundBuffer_Release(DSImpl->dsbuffer); DSImpl->dsbuffer = NULL; } } LeaveCriticalSection(This->pin.pCritSec); return hr; }
static HRESULT WINAPI QTInPin_ReceiveConnection(IPin *iface, IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) { HRESULT hr = S_OK; ALLOCATOR_PROPERTIES props; QTInPin *This = impl_from_IPin(iface); TRACE("(%p/%p)->(%p, %p)\n", This, iface, pReceivePin, pmt); EnterCriticalSection(This->pin.pCritSec); This->pReader = NULL; if (This->pin.pConnectedTo) hr = VFW_E_ALREADY_CONNECTED; else if (IPin_QueryAccept(iface, pmt) != S_OK) hr = VFW_E_TYPE_NOT_ACCEPTED; else { PIN_DIRECTION pindirReceive; IPin_QueryDirection(pReceivePin, &pindirReceive); if (pindirReceive != PINDIR_OUTPUT) hr = VFW_E_INVALID_DIRECTION; } if (FAILED(hr)) { LeaveCriticalSection(This->pin.pCritSec); return hr; } hr = IPin_QueryInterface(pReceivePin, &IID_IAsyncReader, (LPVOID *)&This->pReader); if (FAILED(hr)) { LeaveCriticalSection(This->pin.pCritSec); TRACE("Input source is not an AsyncReader\n"); return hr; } LeaveCriticalSection(This->pin.pCritSec); EnterCriticalSection(&impl_from_IBaseFilter(This->pin.pinInfo.pFilter)->filter.csFilter); hr = QT_Process_Movie(impl_from_IBaseFilter(This->pin.pinInfo.pFilter)); if (FAILED(hr)) { LeaveCriticalSection(&impl_from_IBaseFilter(This->pin.pinInfo.pFilter)->filter.csFilter); TRACE("Unable to process movie\n"); return hr; } This->pAlloc = NULL; props.cBuffers = 8; props.cbAlign = 1; props.cbBuffer = impl_from_IBaseFilter(This->pin.pinInfo.pFilter)->outputSize + props.cbAlign; props.cbPrefix = 0; hr = IAsyncReader_RequestAllocator(This->pReader, NULL, &props, &This->pAlloc); if (SUCCEEDED(hr)) { CopyMediaType(&This->pin.mtCurrent, pmt); This->pin.pConnectedTo = pReceivePin; IPin_AddRef(pReceivePin); hr = IMemAllocator_Commit(This->pAlloc); } else { QT_RemoveOutputPins(impl_from_IBaseFilter(This->pin.pinInfo.pFilter)); if (This->pReader) IAsyncReader_Release(This->pReader); This->pReader = NULL; if (This->pAlloc) IMemAllocator_Release(This->pAlloc); This->pAlloc = NULL; } TRACE("Size: %i\n", props.cbBuffer); LeaveCriticalSection(&impl_from_IBaseFilter(This->pin.pinInfo.pFilter)->filter.csFilter); return hr; }
static HRESULT WINAPI IAMMultiMediaStreamImpl_OpenFile(IAMMultiMediaStream* iface, LPCWSTR pszFileName, DWORD dwFlags) { HRESULT ret; IAMMultiMediaStreamImpl *This = impl_from_IAMMultiMediaStream(iface); IFileSourceFilter *SourceFilter; IBaseFilter *BaseFilter; IEnumPins *EnumPins; IPin *ipin; PIN_DIRECTION pin_direction; TRACE("(%p/%p)->(%s,%x)\n", This, iface, debugstr_w(pszFileName), dwFlags); ret = CoCreateInstance(&CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER, &IID_IFileSourceFilter, (void**)&SourceFilter); if(ret != S_OK) return ret; ret = IFileSourceFilter_Load(SourceFilter, pszFileName, NULL); if(ret != S_OK) { IFileSourceFilter_Release(SourceFilter); return ret; } ret = IFileSourceFilter_QueryInterface(SourceFilter, &IID_IBaseFilter, (void**)&BaseFilter); if(ret != S_OK) { IFileSourceFilter_Release(SourceFilter); return ret; } ret = IBaseFilter_EnumPins(BaseFilter, &EnumPins); if(ret != S_OK) { goto end; } ret = IEnumPins_Next(EnumPins, 1, &ipin, NULL); if(ret == S_OK) { ret = IPin_QueryDirection(ipin, &pin_direction); IEnumPins_Release(EnumPins); if(ret == S_OK && pin_direction == PINDIR_OUTPUT) This->ipin = ipin; else goto end; } else { IEnumPins_Release(EnumPins); goto end; } /* If Initialize was not called before, we do it here */ if (!This->pFilterGraph) { ret = IAMMultiMediaStream_Initialize(iface, STREAMTYPE_READ, 0, NULL); if (FAILED(ret)) goto end; } ret = IFilterGraph_QueryInterface(This->pFilterGraph, &IID_IGraphBuilder, (void**)&This->GraphBuilder); if(ret != S_OK) { goto end; } ret = IGraphBuilder_AddSourceFilter(This->GraphBuilder, pszFileName, pszFileName, &BaseFilter); end: IBaseFilter_Release(BaseFilter); IFileSourceFilter_Release(SourceFilter); return ret; }
/* This test doesn't use the quartz filtergraph because it makes it impossible * to be certain that a thread is really one owned by the avi splitter. * A lot of the decoder filters will also have their own thread, and Windows' * filtergraph has a separate thread for start/stop/seeking requests. * By avoiding the filtergraph altogether and connecting streams directly to * the null renderer I am sure that this is not the case here. */ static void test_threads(void) { IFileSourceFilter *pfile = NULL; IBaseFilter *preader = NULL, *pavi = NULL; IEnumPins *enumpins = NULL; IPin *filepin = NULL, *avipin = NULL; HRESULT hr; int baselevel, curlevel, expected; HANDLE file = NULL; PIN_DIRECTION dir = PINDIR_OUTPUT; char buffer[13]; DWORD readbytes; FILTER_STATE state; /* We need another way of counting threads on NT4. Skip these tests (for now) */ if (!pCreateToolhelp32Snapshot || !pThread32First || !pThread32Next) { win_skip("Needed thread functions are not available (NT4)\n"); return; } /* Before doing anything (the thread count at the start differs per OS) */ baselevel = count_threads(); file = CreateFileW(wfile, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (file == INVALID_HANDLE_VALUE) { skip("Could not read test file \"%s\", skipping test\n", afile); return; } memset(buffer, 0, 13); readbytes = 12; ReadFile(file, buffer, readbytes, &readbytes, NULL); CloseHandle(file); if (strncmp(buffer, "RIFF", 4) || strcmp(buffer + 8, "AVI ")) { skip("%s is not an avi riff file, not doing the avi splitter test\n", afile); return; } hr = IUnknown_QueryInterface(pAviSplitter, &IID_IFileSourceFilter, (void **)&pfile); ok(hr == E_NOINTERFACE, "Avi splitter returns unexpected error: %08x\n", hr); if (pfile) IFileSourceFilter_Release(pfile); pfile = NULL; hr = CoCreateInstance(&CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&preader); ok(hr == S_OK, "Could not create asynchronous reader: %08x\n", hr); if (hr != S_OK) goto fail; hr = IBaseFilter_QueryInterface(preader, &IID_IFileSourceFilter, (void**)&pfile); ok(hr == S_OK, "Could not get IFileSourceFilter: %08x\n", hr); if (hr != S_OK) goto fail; hr = IUnknown_QueryInterface(pAviSplitter, &IID_IBaseFilter, (void**)&pavi); ok(hr == S_OK, "Could not get base filter: %08x\n", hr); if (hr != S_OK) goto fail; hr = IFileSourceFilter_Load(pfile, wfile, NULL); if (hr != S_OK) { trace("Could not load file\n"); goto fail; } hr = IBaseFilter_EnumPins(preader, &enumpins); ok(hr == S_OK, "No enumpins: %08x\n", hr); if (hr != S_OK) goto fail; hr = IEnumPins_Next(enumpins, 1, &filepin, NULL); ok(hr == S_OK, "No pin: %08x\n", hr); if (hr != S_OK) goto fail; IEnumPins_Release(enumpins); enumpins = NULL; hr = IBaseFilter_EnumPins(pavi, &enumpins); ok(hr == S_OK, "No enumpins: %08x\n", hr); if (hr != S_OK) goto fail; hr = IEnumPins_Next(enumpins, 1, &avipin, NULL); ok(hr == S_OK, "No pin: %08x\n", hr); if (hr != S_OK) goto fail; curlevel = count_threads(); ok(curlevel == baselevel, "The thread count should be %d not %d\n", baselevel, curlevel); hr = IPin_Connect(filepin, avipin, NULL); ok(hr == S_OK, "Could not connect: %08x\n", hr); if (hr != S_OK) goto fail; expected = 1 + baselevel; curlevel = count_threads(); ok(curlevel == expected, "The thread count should be %d not %d\n", expected, curlevel); IPin_Release(avipin); avipin = NULL; IEnumPins_Reset(enumpins); /* Windows puts the pins in the order: Outputpins - Inputpin, * wine does the reverse, just don't test it for now * Hate to admit it, but windows way makes more sense */ while (IEnumPins_Next(enumpins, 1, &avipin, NULL) == S_OK) { IPin_QueryDirection(avipin, &dir); if (dir == PINDIR_OUTPUT) { /* Well, connect it to a null renderer! */ IBaseFilter *pnull = NULL; IEnumPins *nullenum = NULL; IPin *nullpin = NULL; hr = CoCreateInstance(&CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pnull); ok(hr == S_OK, "Could not create null renderer: %08x\n", hr); if (hr != S_OK) break; IBaseFilter_EnumPins(pnull, &nullenum); IEnumPins_Next(nullenum, 1, &nullpin, NULL); IEnumPins_Release(nullenum); IPin_QueryDirection(nullpin, &dir); hr = IPin_Connect(avipin, nullpin, NULL); ok(hr == S_OK, "Failed to connect output pin: %08x\n", hr); IPin_Release(nullpin); if (hr != S_OK) { IBaseFilter_Release(pnull); break; } IBaseFilter_Run(pnull, 0); ++expected; } IPin_Release(avipin); avipin = NULL; } if (avipin) IPin_Release(avipin); avipin = NULL; if (hr != S_OK) goto fail2; /* At this point there is a minimalistic connected avi splitter that can * be used for all sorts of source filter tests. However that still needs * to be written at a later time. * * Interesting tests: * - Can you disconnect an output pin while running? * Expecting: Yes * - Can you disconnect the pullpin while running? * Expecting: No * - Is the reference count incremented during playback or when connected? * Does this happen once for every output pin? Or is there something else * going on. * Expecting: You tell me */ IBaseFilter_Run(preader, 0); IBaseFilter_Run(pavi, 0); IBaseFilter_GetState(pavi, INFINITE, &state); curlevel = count_threads(); ok(curlevel == expected, "The thread count should be %d not %d\n", expected, curlevel); IBaseFilter_Pause(pavi); IBaseFilter_Pause(preader); IBaseFilter_Stop(pavi); IBaseFilter_Stop(preader); IBaseFilter_GetState(pavi, INFINITE, &state); IBaseFilter_GetState(preader, INFINITE, &state); fail2: IEnumPins_Reset(enumpins); while (IEnumPins_Next(enumpins, 1, &avipin, NULL) == S_OK) { IPin *to = NULL; IPin_QueryDirection(avipin, &dir); IPin_ConnectedTo(avipin, &to); if (to) { IPin_Release(to); if (dir == PINDIR_OUTPUT) { PIN_INFO info; IPin_QueryPinInfo(to, &info); /* Release twice: Once normal, second from the * previous while loop */ IBaseFilter_Stop(info.pFilter); IPin_Disconnect(to); IPin_Disconnect(avipin); IBaseFilter_Release(info.pFilter); IBaseFilter_Release(info.pFilter); } else { IPin_Disconnect(to); IPin_Disconnect(avipin); } } IPin_Release(avipin); avipin = NULL; } fail: if (hr != S_OK) skip("Prerequisites not matched, skipping remainder of test\n"); if (enumpins) IEnumPins_Release(enumpins); if (avipin) IPin_Release(avipin); if (filepin) { IPin *to = NULL; IPin_ConnectedTo(filepin, &to); if (to) { IPin_Disconnect(filepin); IPin_Disconnect(to); } IPin_Release(filepin); } if (preader) IBaseFilter_Release(preader); if (pavi) IBaseFilter_Release(pavi); if (pfile) IFileSourceFilter_Release(pfile); curlevel = count_threads(); todo_wine ok(curlevel == baselevel, "The thread count should be %d not %d\n", baselevel, curlevel); }
static void test_AviMux(void) { test_filter source_filter, sink_filter; VIDEOINFOHEADER videoinfoheader; IPin *avimux_in, *avimux_out, *pin; AM_MEDIA_TYPE source_media_type; AM_MEDIA_TYPE *media_type; PIN_DIRECTION dir; IBaseFilter *avimux; IEnumPins *ep; IEnumMediaTypes *emt; HRESULT hr; init_test_filter(&source_filter, PINDIR_OUTPUT, SOURCE_FILTER); init_test_filter(&sink_filter, PINDIR_INPUT, SINK_FILTER); hr = CoCreateInstance(&CLSID_AviDest, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (void**)&avimux); ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG), "couldn't create AVI Mux filter, hr = %08x\n", hr); if(hr != S_OK) { win_skip("AVI Mux filter is not registered\n"); return; } hr = IBaseFilter_EnumPins(avimux, &ep); ok(hr == S_OK, "EnumPins returned %x\n", hr); hr = IEnumPins_Next(ep, 1, &avimux_out, NULL); ok(hr == S_OK, "Next returned %x\n", hr); hr = IPin_QueryDirection(avimux_out, &dir); ok(hr == S_OK, "QueryDirection returned %x\n", hr); ok(dir == PINDIR_OUTPUT, "dir = %d\n", dir); hr = IEnumPins_Next(ep, 1, &avimux_in, NULL); ok(hr == S_OK, "Next returned %x\n", hr); hr = IPin_QueryDirection(avimux_in, &dir); ok(hr == S_OK, "QueryDirection returned %x\n", hr); ok(dir == PINDIR_INPUT, "dir = %d\n", dir); IEnumPins_Release(ep); hr = IPin_EnumMediaTypes(avimux_out, &emt); ok(hr == S_OK, "EnumMediaTypes returned %x\n", hr); hr = IEnumMediaTypes_Next(emt, 1, &media_type, NULL); ok(hr == S_OK, "Next returned %x\n", hr); ok(IsEqualIID(&media_type->majortype, &MEDIATYPE_Stream), "majortype = %s\n", debugstr_guid(&media_type->majortype)); ok(IsEqualIID(&media_type->subtype, &MEDIASUBTYPE_Avi), "subtype = %s\n", debugstr_guid(&media_type->subtype)); ok(media_type->bFixedSizeSamples, "bFixedSizeSamples = %x\n", media_type->bFixedSizeSamples); ok(!media_type->bTemporalCompression, "bTemporalCompression = %x\n", media_type->bTemporalCompression); ok(media_type->lSampleSize == 1, "lSampleSize = %d\n", media_type->lSampleSize); ok(IsEqualIID(&media_type->formattype, &GUID_NULL), "formattype = %s\n", debugstr_guid(&media_type->formattype)); ok(!media_type->pUnk, "pUnk = %p\n", media_type->pUnk); ok(!media_type->cbFormat, "cbFormat = %d\n", media_type->cbFormat); ok(!media_type->pbFormat, "pbFormat = %p\n", media_type->pbFormat); CoTaskMemFree(media_type); hr = IEnumMediaTypes_Next(emt, 1, &media_type, NULL); ok(hr == S_FALSE, "Next returned %x\n", hr); IEnumMediaTypes_Release(emt); hr = IPin_EnumMediaTypes(avimux_in, &emt); ok(hr == S_OK, "EnumMediaTypes returned %x\n", hr); hr = IEnumMediaTypes_Reset(emt); ok(hr == S_OK, "Reset returned %x\n", hr); hr = IEnumMediaTypes_Next(emt, 1, &media_type, NULL); ok(hr == S_FALSE, "Next returned %x\n", hr); IEnumMediaTypes_Release(emt); hr = IPin_ReceiveConnection(avimux_in, &source_filter.IPin_iface, NULL); ok(hr == E_POINTER, "ReceiveConnection returned %x\n", hr); current_calls_list = NULL; memset(&source_media_type, 0, sizeof(AM_MEDIA_TYPE)); memset(&videoinfoheader, 0, sizeof(VIDEOINFOHEADER)); source_media_type.majortype = MEDIATYPE_Video; source_media_type.subtype = MEDIASUBTYPE_RGB32; source_media_type.formattype = FORMAT_VideoInfo; source_media_type.bFixedSizeSamples = TRUE; source_media_type.lSampleSize = 40000; source_media_type.cbFormat = sizeof(VIDEOINFOHEADER); source_media_type.pbFormat = (BYTE*)&videoinfoheader; videoinfoheader.AvgTimePerFrame = 333333; videoinfoheader.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); videoinfoheader.bmiHeader.biWidth = 100; videoinfoheader.bmiHeader.biHeight = 100; videoinfoheader.bmiHeader.biPlanes = 1; videoinfoheader.bmiHeader.biBitCount = 32; videoinfoheader.bmiHeader.biSizeImage = 40000; videoinfoheader.bmiHeader.biClrImportant = 256; hr = IPin_ReceiveConnection(avimux_in, &source_filter.IPin_iface, &source_media_type); ok(hr == S_OK, "ReceiveConnection returned %x\n", hr); hr = IPin_ConnectedTo(avimux_in, &pin); ok(hr == S_OK, "ConnectedTo returned %x\n", hr); ok(pin == &source_filter.IPin_iface, "incorrect pin: %p, expected %p\n", pin, &source_filter.IPin_iface); hr = IPin_Connect(avimux_out, &source_filter.IPin_iface, NULL); todo_wine ok(hr == VFW_E_INVALID_DIRECTION, "Connect returned %x\n", hr); hr = IBaseFilter_JoinFilterGraph(avimux, (IFilterGraph*)&GraphBuilder, NULL); ok(hr == S_OK, "JoinFilterGraph returned %x\n", hr); SET_EXPECT(ReceiveConnection); SET_EXPECT(GetAllocatorRequirements); SET_EXPECT(NotifyAllocator); SET_EXPECT(Reconnect); hr = IPin_Connect(avimux_out, &sink_filter.IPin_iface, NULL); ok(hr == S_OK, "Connect returned %x\n", hr); CHECK_CALLED(ReceiveConnection); CHECK_CALLED(GetAllocatorRequirements); CHECK_CALLED(NotifyAllocator); CHECK_CALLED(Reconnect); hr = IPin_Disconnect(avimux_out); ok(hr == S_OK, "Disconnect returned %x\n", hr); IPin_Release(avimux_in); IPin_Release(avimux_out); IBaseFilter_Release(avimux); }