diff --git a/dlls/qcap/smartteefilter.c b/dlls/qcap/smartteefilter.c index 9af2e9a4d0c..d550169e19d 100644 --- a/dlls/qcap/smartteefilter.c +++ b/dlls/qcap/smartteefilter.c @@ -374,12 +374,13 @@ static HRESULT WINAPI SmartTeeFilterCapture_GetMediaType(BasePin *base, int iPos return S_FALSE; } -static HRESULT WINAPI SmartTeeFilterCapture_DecideBufferSize(BaseOutputPin *base, IMemAllocator *alloc, - ALLOCATOR_PROPERTIES *ppropInputRequest) +static HRESULT WINAPI SmartTeeFilterCapture_DecideAllocator(BaseOutputPin *base, IMemInputPin *pPin, IMemAllocator **pAlloc) { SmartTeeFilter *This = impl_from_BasePin(&base->pin); - FIXME("(%p, %p, %p): stub\n", This, alloc, ppropInputRequest); - return E_NOTIMPL; + TRACE("(%p, %p, %p)\n", This, pPin, pAlloc); + *pAlloc = This->input->pAllocator; + IMemAllocator_AddRef(This->input->pAllocator); + return IMemInputPin_NotifyAllocator(pPin, This->input->pAllocator, TRUE); } static HRESULT WINAPI SmartTeeFilterCapture_BreakConnect(BaseOutputPin *base) @@ -396,8 +397,8 @@ static const BaseOutputPinFuncTable SmartTeeFilterCaptureFuncs = { SmartTeeFilterCapture_GetMediaTypeVersion, SmartTeeFilterCapture_GetMediaType }, - SmartTeeFilterCapture_DecideBufferSize, - BaseOutputPinImpl_DecideAllocator, + NULL, + SmartTeeFilterCapture_DecideAllocator, SmartTeeFilterCapture_BreakConnect }; @@ -466,11 +467,13 @@ static HRESULT WINAPI SmartTeeFilterPreview_GetMediaType(BasePin *base, int iPos return S_FALSE; } -static HRESULT WINAPI SmartTeeFilterPreview_DecideBufferSize(BaseOutputPin *base, IMemAllocator *alloc, ALLOCATOR_PROPERTIES *ppropInputRequest) +static HRESULT WINAPI SmartTeeFilterPreview_DecideAllocator(BaseOutputPin *base, IMemInputPin *pPin, IMemAllocator **pAlloc) { SmartTeeFilter *This = impl_from_BasePin(&base->pin); - FIXME("(%p, %p, %p): stub\n", This, alloc, ppropInputRequest); - return E_NOTIMPL; + TRACE("(%p, %p, %p)\n", This, pPin, pAlloc); + *pAlloc = This->input->pAllocator; + IMemAllocator_AddRef(This->input->pAllocator); + return IMemInputPin_NotifyAllocator(pPin, This->input->pAllocator, TRUE); } static HRESULT WINAPI SmartTeeFilterPreview_BreakConnect(BaseOutputPin *base) @@ -487,8 +490,8 @@ static const BaseOutputPinFuncTable SmartTeeFilterPreviewFuncs = { SmartTeeFilterPreview_GetMediaTypeVersion, SmartTeeFilterPreview_GetMediaType }, - SmartTeeFilterPreview_DecideBufferSize, - BaseOutputPinImpl_DecideAllocator, + NULL, + SmartTeeFilterPreview_DecideAllocator, SmartTeeFilterPreview_BreakConnect }; IUnknown* WINAPI QCAP_createSmartTeeFilter(IUnknown *outer, HRESULT *phr) @@ -521,6 +524,10 @@ IUnknown* WINAPI QCAP_createSmartTeeFilter(IUnknown *outer, HRESULT *phr) &SmartTeeFilterInputFuncs, &This->filter.csFilter, NULL, (IPin**)&This->input); if (FAILED(hr)) goto end; + hr = CoCreateInstance(&CLSID_MemoryAllocator, NULL, CLSCTX_INPROC_SERVER, + &IID_IMemAllocator, (void**)&This->input->pAllocator); + if (FAILED(hr)) + goto end; capturePinInfo.pFilter = &This->filter.IBaseFilter_iface; hr = BaseOutputPin_Construct(&SmartTeeFilterCaptureVtbl, sizeof(BaseOutputPin), &capturePinInfo, diff --git a/dlls/qcap/tests/smartteefilter.c b/dlls/qcap/tests/smartteefilter.c index 12558871372..e23e66f8e56 100644 --- a/dlls/qcap/tests/smartteefilter.c +++ b/dlls/qcap/tests/smartteefilter.c @@ -41,6 +41,7 @@ typedef struct { DWORD receiveThreadId; IPin IPin_iface; IMemInputPin IMemInputPin_iface; + IMemAllocator *allocator; IBaseFilter *nullRenderer; IPin *nullRendererPin; IMemInputPin *nullRendererMemInputPin; @@ -106,6 +107,8 @@ static ULONG WINAPI SinkFilter_Release(IBaseFilter *iface) SinkFilter *This = impl_from_SinkFilter_IBaseFilter(iface); ULONG ref = InterlockedDecrement(&This->ref); if(!ref) { + if (This->allocator) + IMemAllocator_Release(This->allocator); IMemInputPin_Release(This->nullRendererMemInputPin); IPin_Release(This->nullRendererPin); IBaseFilter_Release(This->nullRenderer); @@ -493,6 +496,7 @@ static ULONG WINAPI SinkMemInputPin_Release(IMemInputPin *iface) static HRESULT WINAPI SinkMemInputPin_GetAllocator(IMemInputPin *iface, IMemAllocator **ppAllocator) { SinkFilter *This = impl_from_SinkFilter_IMemInputPin(iface); + ok(0, "SmartTeeFilter never calls IMemInputPin_GetAllocator()\n"); return IMemInputPin_GetAllocator(This->nullRendererMemInputPin, ppAllocator); } @@ -500,6 +504,9 @@ static HRESULT WINAPI SinkMemInputPin_NotifyAllocator(IMemInputPin *iface, IMemA BOOL bReadOnly) { SinkFilter *This = impl_from_SinkFilter_IMemInputPin(iface); + This->allocator = pAllocator; + IMemAllocator_AddRef(This->allocator); + ok(bReadOnly, "bReadOnly isn't supposed to be FALSE\n"); return IMemInputPin_NotifyAllocator(This->nullRendererMemInputPin, pAllocator, bReadOnly); } @@ -507,6 +514,7 @@ static HRESULT WINAPI SinkMemInputPin_GetAllocatorRequirements(IMemInputPin *ifa ALLOCATOR_PROPERTIES *pProps) { SinkFilter *This = impl_from_SinkFilter_IMemInputPin(iface); + ok(0, "SmartTeeFilter never calls IMemInputPin_GetAllocatorRequirements()\n"); return IMemInputPin_GetAllocatorRequirements(This->nullRendererMemInputPin, pProps); } @@ -727,7 +735,7 @@ static DWORD WINAPI media_thread(LPVOID param) } hr = IMemInputPin_Receive(This->memInputPin, sample); - ok(SUCCEEDED(hr), "delivering sample to SmartTeeFilter's Input pin failed, hr=0x%08x\n", hr); + todo_wine ok(SUCCEEDED(hr), "delivering sample to SmartTeeFilter's Input pin failed, hr=0x%08x\n", hr); IMediaSample_Release(sample); } @@ -1016,7 +1024,7 @@ static HRESULT WINAPI SourcePin_Connect(IPin *iface, IPin *pReceivePin, const AM hr = IPin_QueryInterface(pReceivePin, &IID_IMemInputPin, (void**)&This->memInputPin); if (SUCCEEDED(hr)) { hr = IMemInputPin_GetAllocator(This->memInputPin, &This->allocator); - todo_wine ok(SUCCEEDED(hr), "couldn't get allocator from SmartTeeFilter, hr=0x%08x\n", hr); + ok(SUCCEEDED(hr), "couldn't get allocator from SmartTeeFilter, hr=0x%08x\n", hr); if (SUCCEEDED(hr)) { ALLOCATOR_PROPERTIES requested, actual; ZeroMemory(&requested, sizeof(ALLOCATOR_PROPERTIES)); @@ -1272,6 +1280,7 @@ static void test_smart_tee_filter_in_graph(IBaseFilter *smartTeeFilter, IPin *in SourceFilter *sourceFilter = NULL; SinkFilter *captureSinkFilter = NULL; SinkFilter *previewSinkFilter = NULL; + DWORD endTime; hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IGraphBuilder, (LPVOID*)&graphBuilder); @@ -1322,7 +1331,7 @@ static void test_smart_tee_filter_in_graph(IBaseFilter *smartTeeFilter, IPin *in goto end; hr = IGraphBuilder_Connect(graphBuilder, &sourceFilter->IPin_iface, inputPin); - todo_wine ok(SUCCEEDED(hr), "couldn't connect source filter to Input pin, hr=0x%08x\n", hr); + ok(SUCCEEDED(hr), "couldn't connect source filter to Input pin, hr=0x%08x\n", hr); if (FAILED(hr)) goto end; hr = IGraphBuilder_Connect(graphBuilder, capturePin, &captureSinkFilter->IPin_iface); @@ -1334,6 +1343,9 @@ static void test_smart_tee_filter_in_graph(IBaseFilter *smartTeeFilter, IPin *in if (FAILED(hr)) goto end; + ok(sourceFilter->allocator == captureSinkFilter->allocator, "input and capture allocators don't match\n"); + ok(sourceFilter->allocator == previewSinkFilter->allocator, "input and preview allocators don't match\n"); + hr = IGraphBuilder_QueryInterface(graphBuilder, &IID_IMediaControl, (void**)&mediaControl); ok(SUCCEEDED(hr), "couldn't get IMediaControl interface from IGraphBuilder, hr=0x%08x\n", hr); if (FAILED(hr)) @@ -1343,14 +1355,24 @@ static void test_smart_tee_filter_in_graph(IBaseFilter *smartTeeFilter, IPin *in if (FAILED(hr)) goto end; - while (previewSinkFilter->receiveThreadId == 0 || captureSinkFilter->receiveThreadId == 0) - WaitForSingleObject(event, INFINITE); - ok(sourceFilter->mediaThreadId != captureSinkFilter->receiveThreadId, - "sending thread should != capture receiving thread\n"); - ok(sourceFilter->mediaThreadId != previewSinkFilter->receiveThreadId, - "sending thread should != preview receiving thread\n"); - ok(captureSinkFilter->receiveThreadId != previewSinkFilter->receiveThreadId, - "capture receiving thread should != preview receiving thread"); + endTime = GetTickCount() + 5000; + while (previewSinkFilter->receiveThreadId == 0 || captureSinkFilter->receiveThreadId == 0) { + DWORD now = GetTickCount(); + if (now < endTime) + WaitForSingleObject(event, endTime - now); + else + break; + } + if (previewSinkFilter->receiveThreadId != 0 && captureSinkFilter->receiveThreadId != 0) { + ok(sourceFilter->mediaThreadId != captureSinkFilter->receiveThreadId, + "sending thread should != capture receiving thread\n"); + ok(sourceFilter->mediaThreadId != previewSinkFilter->receiveThreadId, + "sending thread should != preview receiving thread\n"); + ok(captureSinkFilter->receiveThreadId != previewSinkFilter->receiveThreadId, + "capture receiving thread should != preview receiving thread"); + } else { + todo_wine ok(0, "timeout: threads did not receive sample in time\n"); + } IMediaControl_Stop(mediaControl);