diff --git a/reactos/CMakeLists.txt b/reactos/CMakeLists.txt index 7a7c2cad321..e900205c757 100644 --- a/reactos/CMakeLists.txt +++ b/reactos/CMakeLists.txt @@ -202,8 +202,8 @@ else() include/psdk include/dxsdk ${REACTOS_BINARY_DIR}/include - ${REACTOS_BINARY_DIR}/include/dxsdk ${REACTOS_BINARY_DIR}/include/psdk + ${REACTOS_BINARY_DIR}/include/dxsdk ${REACTOS_BINARY_DIR}/include/reactos include/crt include/ddk diff --git a/reactos/dll/directx/devenum/createdevenum.c b/reactos/dll/directx/devenum/createdevenum.c index 936ba4d07de..bbe93523ddb 100644 --- a/reactos/dll/directx/devenum/createdevenum.c +++ b/reactos/dll/directx/devenum/createdevenum.c @@ -258,7 +258,7 @@ static void DEVENUM_ReadPins(HKEY hkeyFilterClass, REGFILTER2 *rgf2) WCHAR wszPinName[MAX_PATH]; DWORD cName = sizeof(wszPinName) / sizeof(WCHAR); DWORD Type, cbData; - REGFILTERPINS *rgPin = &rgPins[rgf2->u.s.cPins]; + REGFILTERPINS *rgPin = &rgPins[rgf2->u.s1.cPins]; LONG lRet; rgPin->strName = NULL; @@ -298,7 +298,7 @@ static void DEVENUM_ReadPins(HKEY hkeyFilterClass, REGFILTER2 *rgf2) DEVENUM_ReadPinTypes(hkeyPinKey, rgPin); - ++rgf2->u.s.cPins; + ++rgf2->u.s1.cPins; continue; error_cleanup: @@ -309,13 +309,13 @@ static void DEVENUM_ReadPins(HKEY hkeyFilterClass, REGFILTER2 *rgf2) RegCloseKey(hkeyPins); - if (rgPins && !rgf2->u.s.cPins) + if (rgPins && !rgf2->u.s1.cPins) { CoTaskMemFree(rgPins); rgPins = NULL; } - rgf2->u.s.rgPins = rgPins; + rgf2->u.s1.rgPins = rgPins; } static HRESULT DEVENUM_RegisterLegacyAmFilters(void) @@ -387,8 +387,8 @@ static HRESULT DEVENUM_RegisterLegacyAmFilters(void) rgf2.dwVersion = 1; rgf2.dwMerit = 0; - rgf2.u.s.cPins = 0; - rgf2.u.s.rgPins = NULL; + rgf2.u.s1.cPins = 0; + rgf2.u.s1.rgPins = NULL; cbData = sizeof(wszFilterName); if (RegQueryValueExW(hkeyFilterClass, NULL, NULL, &Type, (LPBYTE)wszFilterName, &cbData) != ERROR_SUCCESS || @@ -414,29 +414,29 @@ static HRESULT DEVENUM_RegisterLegacyAmFilters(void) if (hkeyFilterClass) RegCloseKey(hkeyFilterClass); - if (rgf2.u.s.rgPins) + if (rgf2.u.s1.rgPins) { UINT iPin; - for (iPin = 0; iPin < rgf2.u.s.cPins; iPin++) + for (iPin = 0; iPin < rgf2.u.s1.cPins; iPin++) { - CoTaskMemFree(rgf2.u.s.rgPins[iPin].strName); + CoTaskMemFree(rgf2.u.s1.rgPins[iPin].strName); - if (rgf2.u.s.rgPins[iPin].lpMediaType) + if (rgf2.u.s1.rgPins[iPin].lpMediaType) { UINT iType; - for (iType = 0; iType < rgf2.u.s.rgPins[iPin].nMediaTypes; iType++) + for (iType = 0; iType < rgf2.u.s1.rgPins[iPin].nMediaTypes; iType++) { - CoTaskMemFree((void*)rgf2.u.s.rgPins[iPin].lpMediaType[iType].clsMajorType); - CoTaskMemFree((void*)rgf2.u.s.rgPins[iPin].lpMediaType[iType].clsMinorType); + CoTaskMemFree((void*)rgf2.u.s1.rgPins[iPin].lpMediaType[iType].clsMajorType); + CoTaskMemFree((void*)rgf2.u.s1.rgPins[iPin].lpMediaType[iType].clsMinorType); } - CoTaskMemFree((void*)rgf2.u.s.rgPins[iPin].lpMediaType); + CoTaskMemFree((void*)rgf2.u.s1.rgPins[iPin].lpMediaType); } } - CoTaskMemFree((void*)rgf2.u.s.rgPins); + CoTaskMemFree((void*)rgf2.u.s1.rgPins); } } } @@ -606,8 +606,8 @@ static HRESULT DEVENUM_CreateSpecialCategories(void) rf2.dwVersion = 2; rf2.dwMerit = MERIT_PREFERRED; - rf2.u.s1.cPins2 = 1; - rf2.u.s1.rgPins2 = &rfp2; + rf2.u.s2.cPins2 = 1; + rf2.u.s2.rgPins2 = &rfp2; rfp2.cInstances = 1; rfp2.nMediums = 0; rfp2.lpMedium = NULL; diff --git a/reactos/dll/directx/quartz/CMakeLists.txt b/reactos/dll/directx/quartz/CMakeLists.txt index f0f6a57e050..11092724cfe 100644 --- a/reactos/dll/directx/quartz/CMakeLists.txt +++ b/reactos/dll/directx/quartz/CMakeLists.txt @@ -5,49 +5,57 @@ add_definitions(-D_WIN32_WINNT=0x600) add_definitions( -D__WINESRC__ -DENTRY_PREFIX=QUARTZ_ - -DREGISTER_PROXY_DLL + -DWINE_REGISTER_DLL -DPROXY_DELEGATION) include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine) - spec2def(quartz.dll quartz.spec) - add_rpcproxy_files(quartz_strmif.idl) list(APPEND SOURCE - avidec.c acmwrapper.c - waveparser.c - videorenderer.c - transform.c - systemclock.c - regsvr.c - pin.c - parser.c - nullrenderer.c - mpegsplit.c - memallocator.c - main.c - filtermapper.c - filtergraph.c - filesource.c - enumregfilters.c - enumpins.c - enummoniker.c - enumfilters.c - dsoundrender.c - enummedia.c - control.c + avidec.c avisplit.c + dsoundrender.c + enumfilters.c + enummedia.c + enummoniker.c + enumregfilters.c + filesource.c + filtergraph.c + filtermapper.c + main.c + memallocator.c + mpegsplit.c + nullrenderer.c + parser.c + pin.c + regsvr.c + systemclock.c + videorenderer.c + vmr9.c + waveparser.c ${CMAKE_CURRENT_BINARY_DIR}/proxy.dlldata.c ${CMAKE_CURRENT_BINARY_DIR}/quartz_strmif_p.c ${CMAKE_CURRENT_BINARY_DIR}/quartz.def) add_library(quartz SHARED ${SOURCE} version.rc) + +add_idl_headers(quartz_idlheader fil_data.idl) + +add_typelib(control_tlb.idl) + +list(APPEND quartz_rc_deps + ${CMAKE_CURRENT_BINARY_DIR}/control_tlb.tlb + ${CMAKE_CURRENT_SOURCE_DIR}/control_tlb.rgs + ${CMAKE_CURRENT_SOURCE_DIR}/quartz_strmif.rgs) + +set_source_files_properties(version.rc PROPERTIES OBJECT_DEPENDS "${quartz_rc_deps}") + set_module_type(quartz win32dll) -target_link_libraries(quartz strmiids uuid wine ${PSEH_LIB}) -add_importlibs(quartz dsound ole32 oleaut32 shlwapi user32 gdi32 advapi32 msvfw32 msacm32 rpcrt4 msvcrt kernel32 ntdll) -add_dependencies(quartz dxsdk) +target_link_libraries(quartz strmbase strmiids uuid dxguid wine ${PSEH_LIB}) +add_importlibs(quartz dsound msacm32 msvfw32 ole32 oleaut32 shlwapi rpcrt4 user32 gdi32 advapi32 msvcrt kernel32 ntdll) +add_dependencies(quartz dxsdk quartz_idlheader stdole2) add_pch(quartz quartz_private.h) add_cd_file(TARGET quartz DESTINATION reactos/system32 FOR all) diff --git a/reactos/dll/directx/quartz/acmwrapper.c b/reactos/dll/directx/quartz/acmwrapper.c index e40cfeca0fe..8c036d2f0e0 100644 --- a/reactos/dll/directx/quartz/acmwrapper.c +++ b/reactos/dll/directx/quartz/acmwrapper.c @@ -37,13 +37,12 @@ //#include "wine/unicode.h" #include -#include "transform.h" - WINE_DEFAULT_DEBUG_CHANNEL(quartz); typedef struct ACMWrapperImpl { - TransformFilterImpl tf; + TransformFilter tf; + HACMSTREAM has; LPWAVEFORMATEX pWfIn; LPWAVEFORMATEX pWfOut; @@ -52,9 +51,21 @@ typedef struct ACMWrapperImpl LONGLONG lasttime_sent; } ACMWrapperImpl; -static HRESULT ACMWrapper_ProcessSampleData(InputPin *pin, IMediaSample *pSample) +static const IBaseFilterVtbl ACMWrapper_Vtbl; + +static inline ACMWrapperImpl *impl_from_TransformFilter( TransformFilter *iface ) { - ACMWrapperImpl* This = (ACMWrapperImpl*)pin->pin.pinInfo.pFilter; + return CONTAINING_RECORD(iface, ACMWrapperImpl, tf.filter); +} + +static inline ACMWrapperImpl *impl_from_IBaseFilter( IBaseFilter *iface ) +{ + return CONTAINING_RECORD(iface, ACMWrapperImpl, tf.filter.IBaseFilter_iface); +} + +static HRESULT WINAPI ACMWrapper_Receive(TransformFilter *tf, IMediaSample *pSample) +{ + ACMWrapperImpl* This = impl_from_TransformFilter(tf); AM_MEDIA_TYPE amt; IMediaSample* pOutSample = NULL; DWORD cbDstStream, cbSrcStream; @@ -65,31 +76,22 @@ static HRESULT ACMWrapper_ProcessSampleData(InputPin *pin, IMediaSample *pSample MMRESULT res; HRESULT hr; LONGLONG tStart = -1, tStop = -1, tMed; + LONGLONG mtStart = -1, mtStop = -1, mtMed; - EnterCriticalSection(&This->tf.csFilter); - if (This->tf.state == State_Stopped) - { - LeaveCriticalSection(&This->tf.csFilter); - return VFW_E_WRONG_STATE; - } - - if (pin->end_of_stream || pin->flushing) - { - LeaveCriticalSection(&This->tf.csFilter); - return S_FALSE; - } - + EnterCriticalSection(&This->tf.csReceive); hr = IMediaSample_GetPointer(pSample, &pbSrcStream); if (FAILED(hr)) { ERR("Cannot get pointer to sample data (%x)\n", hr); - LeaveCriticalSection(&This->tf.csFilter); + LeaveCriticalSection(&This->tf.csReceive); return hr; } preroll = (IMediaSample_IsPreroll(pSample) == S_OK); IMediaSample_GetTime(pSample, &tStart, &tStop); + if (IMediaSample_GetMediaTime(pSample, &mtStart, &mtStop) != S_OK) + mtStart = mtStop = -1; cbSrcStream = IMediaSample_GetActualDataLength(pSample); /* Prevent discontinuities when codecs 'absorb' data but not give anything back in return */ @@ -104,6 +106,7 @@ static HRESULT ACMWrapper_ProcessSampleData(InputPin *pin, IMediaSample *pSample WARN("Discontinuity\n"); tMed = tStart; + mtMed = mtStart; TRACE("Sample data ptr = %p, size = %d\n", pbSrcStream, cbSrcStream); @@ -111,7 +114,7 @@ static HRESULT ACMWrapper_ProcessSampleData(InputPin *pin, IMediaSample *pSample if (FAILED(hr)) { ERR("Unable to retrieve media type\n"); - LeaveCriticalSection(&This->tf.csFilter); + LeaveCriticalSection(&This->tf.csReceive); return hr; } @@ -120,11 +123,11 @@ static HRESULT ACMWrapper_ProcessSampleData(InputPin *pin, IMediaSample *pSample while(hr == S_OK && ash.cbSrcLength) { - hr = OutputPin_GetDeliveryBuffer((OutputPin*)This->tf.ppPins[1], &pOutSample, NULL, NULL, 0); + hr = BaseOutputPinImpl_GetDeliveryBuffer((BaseOutputPin*)This->tf.ppPins[1], &pOutSample, NULL, NULL, 0); if (FAILED(hr)) { ERR("Unable to get delivery buffer (%x)\n", hr); - LeaveCriticalSection(&This->tf.csFilter); + LeaveCriticalSection(&This->tf.csReceive); return hr; } IMediaSample_SetPreroll(pOutSample, preroll); @@ -176,7 +179,7 @@ static HRESULT ACMWrapper_ProcessSampleData(InputPin *pin, IMediaSample *pSample hr = IMediaSample_SetActualDataLength(pOutSample, ash.cbDstLengthUsed); assert(hr == S_OK); - /* Bug in acm codecs? It apparantly uses the input, but doesn't necessarily output immediately kl*/ + /* Bug in acm codecs? It apparently uses the input, but doesn't necessarily output immediately */ if (!ash.cbSrcLengthUsed) { WARN("Sample was skipped? Outputted: %u\n", ash.cbDstLengthUsed); @@ -202,11 +205,26 @@ static HRESULT ACMWrapper_ProcessSampleData(InputPin *pin, IMediaSample *pSample ERR("No valid timestamp found\n"); IMediaSample_SetTime(pOutSample, NULL, NULL); } + + if (mtStart < 0) { + IMediaSample_SetMediaTime(pOutSample, NULL, NULL); + } else if (ash.cbSrcLengthUsed == cbSrcStream) { + IMediaSample_SetMediaTime(pOutSample, &mtStart, &mtStop); + mtStart = mtMed = mtStop; + } else if (mtStop >= mtStart) { + mtMed = mtStop - mtStart; + mtMed = mtStart + mtMed * ash.cbSrcLengthUsed / cbSrcStream; + IMediaSample_SetMediaTime(pOutSample, &mtStart, &mtMed); + mtStart = mtMed; + } else { + IMediaSample_SetMediaTime(pOutSample, NULL, NULL); + } + TRACE("Sample stop time: %u.%03u\n", (DWORD)(tStart/10000000), (DWORD)((tStart/10000)%1000)); - LeaveCriticalSection(&This->tf.csFilter); - hr = OutputPin_SendSample((OutputPin*)This->tf.ppPins[1], pOutSample); - EnterCriticalSection(&This->tf.csFilter); + LeaveCriticalSection(&This->tf.csReceive); + hr = BaseOutputPinImpl_Deliver((BaseOutputPin*)This->tf.ppPins[1], pOutSample); + EnterCriticalSection(&This->tf.csReceive); if (hr != S_OK && hr != VFW_E_NOT_CONNECTED) { if (FAILED(hr)) @@ -221,8 +239,7 @@ error: ash.pbSrc += ash.cbSrcLengthUsed; ash.cbSrcLength -= ash.cbSrcLengthUsed; - if (pOutSample) - IMediaSample_Release(pOutSample); + IMediaSample_Release(pOutSample); pOutSample = NULL; } @@ -230,16 +247,19 @@ error: This->lasttime_real = tStop; This->lasttime_sent = tMed; - LeaveCriticalSection(&This->tf.csFilter); + LeaveCriticalSection(&This->tf.csReceive); return hr; } -static HRESULT ACMWrapper_ConnectInput(InputPin *pin, const AM_MEDIA_TYPE * pmt) +static HRESULT WINAPI ACMWrapper_SetMediaType(TransformFilter *tf, PIN_DIRECTION dir, const AM_MEDIA_TYPE * pmt) { - ACMWrapperImpl* This = (ACMWrapperImpl *)pin->pin.pinInfo.pFilter; + ACMWrapperImpl* This = impl_from_TransformFilter(tf); MMRESULT res; - TRACE("(%p)->(%p)\n", This, pmt); + TRACE("(%p)->(%i %p)\n", This, dir, pmt); + + if (dir != PINDIR_INPUT) + return S_OK; /* Check root (GUID w/o FOURCC) */ if ((IsEqualIID(&pmt->majortype, &MEDIATYPE_Audio)) && @@ -247,7 +267,11 @@ static HRESULT ACMWrapper_ConnectInput(InputPin *pin, const AM_MEDIA_TYPE * pmt) (IsEqualIID(&pmt->formattype, &FORMAT_WaveFormatEx))) { HACMSTREAM drv; + WAVEFORMATEX *wfx = (WAVEFORMATEX*)pmt->pbFormat; AM_MEDIA_TYPE* outpmt = &This->tf.pmt; + + if (!wfx || wfx->wFormatTag == WAVE_FORMAT_PCM || wfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE) + return VFW_E_TYPE_NOT_ACCEPTED; FreeMediaType(outpmt); This->pWfIn = (LPWAVEFORMATEX)pmt->pbFormat; @@ -271,8 +295,6 @@ static HRESULT ACMWrapper_ConnectInput(InputPin *pin, const AM_MEDIA_TYPE * pmt) { This->has = drv; - /* Update buffer size of media samples in output */ - ((OutputPin*)This->tf.ppPins[1])->allocProps.cbBuffer = This->pWfOut->nAvgBytesPerSec / 2; TRACE("Connection accepted\n"); return S_OK; } @@ -286,28 +308,78 @@ static HRESULT ACMWrapper_ConnectInput(InputPin *pin, const AM_MEDIA_TYPE * pmt) return VFW_E_TYPE_NOT_ACCEPTED; } -static HRESULT ACMWrapper_Cleanup(InputPin *pin) +static HRESULT WINAPI ACMWrapper_CompleteConnect(TransformFilter *tf, PIN_DIRECTION dir, IPin *pin) { - ACMWrapperImpl *This = (ACMWrapperImpl *)pin->pin.pinInfo.pFilter; + ACMWrapperImpl* This = impl_from_TransformFilter(tf); + MMRESULT res; + HACMSTREAM drv; - TRACE("(%p)->()\n", This); + TRACE("(%p)\n", This); - if (This->has) - acmStreamClose(This->has, 0); + if (dir != PINDIR_INPUT) + return S_OK; - This->has = 0; - This->lasttime_real = This->lasttime_sent = -1; + if (!(res = acmStreamOpen(&drv, NULL, This->pWfIn, This->pWfOut, NULL, 0, 0, 0))) + { + This->has = drv; + + TRACE("Connection accepted\n"); + return S_OK; + } + + FIXME("acmStreamOpen returned %d\n", res); + TRACE("Unable to find a suitable ACM decompressor\n"); + return VFW_E_TYPE_NOT_ACCEPTED; +} + +static HRESULT WINAPI ACMWrapper_BreakConnect(TransformFilter *tf, PIN_DIRECTION dir) +{ + ACMWrapperImpl *This = impl_from_TransformFilter(tf); + + TRACE("(%p)->(%i)\n", This,dir); + + if (dir == PINDIR_INPUT) + { + if (This->has) + acmStreamClose(This->has, 0); + + This->has = 0; + This->lasttime_real = This->lasttime_sent = -1; + } return S_OK; } -static const TransformFuncsTable ACMWrapper_FuncsTable = { +static HRESULT WINAPI ACMWrapper_DecideBufferSize(TransformFilter *tf, IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest) +{ + ACMWrapperImpl *pACM = impl_from_TransformFilter(tf); + ALLOCATOR_PROPERTIES actual; + + if (!ppropInputRequest->cbAlign) + ppropInputRequest->cbAlign = 1; + + if (ppropInputRequest->cbBuffer < pACM->pWfOut->nAvgBytesPerSec / 2) + ppropInputRequest->cbBuffer = pACM->pWfOut->nAvgBytesPerSec / 2; + + if (!ppropInputRequest->cBuffers) + ppropInputRequest->cBuffers = 1; + + return IMemAllocator_SetProperties(pAlloc, ppropInputRequest, &actual); +} + +static const TransformFilterFuncTable ACMWrapper_FuncsTable = { + ACMWrapper_DecideBufferSize, NULL, - ACMWrapper_ProcessSampleData, + ACMWrapper_Receive, NULL, NULL, - ACMWrapper_ConnectInput, - ACMWrapper_Cleanup + ACMWrapper_SetMediaType, + ACMWrapper_CompleteConnect, + ACMWrapper_BreakConnect, + NULL, + NULL, + NULL, + NULL }; HRESULT ACMWrapper_create(IUnknown * pUnkOuter, LPVOID * ppv) @@ -322,11 +394,7 @@ HRESULT ACMWrapper_create(IUnknown * pUnkOuter, LPVOID * ppv) if (pUnkOuter) return CLASS_E_NOAGGREGATION; - /* Note: This memory is managed by the transform filter once created */ - This = CoTaskMemAlloc(sizeof(ACMWrapperImpl)); - ZeroMemory(This, sizeof(ACMWrapperImpl)); - - hr = TransformFilter_Create(&(This->tf), &CLSID_ACMWrapper, &ACMWrapper_FuncsTable, NULL, NULL, NULL); + hr = TransformFilter_Construct(&ACMWrapper_Vtbl, sizeof(ACMWrapperImpl), &CLSID_ACMWrapper, &ACMWrapper_FuncsTable, (IBaseFilter**)&This); if (FAILED(hr)) return hr; @@ -336,3 +404,22 @@ HRESULT ACMWrapper_create(IUnknown * pUnkOuter, LPVOID * ppv) return hr; } + +static const IBaseFilterVtbl ACMWrapper_Vtbl = +{ + TransformFilterImpl_QueryInterface, + BaseFilterImpl_AddRef, + TransformFilterImpl_Release, + BaseFilterImpl_GetClassID, + TransformFilterImpl_Stop, + TransformFilterImpl_Pause, + TransformFilterImpl_Run, + BaseFilterImpl_GetState, + BaseFilterImpl_SetSyncSource, + BaseFilterImpl_GetSyncSource, + BaseFilterImpl_EnumPins, + TransformFilterImpl_FindPin, + BaseFilterImpl_QueryFilterInfo, + BaseFilterImpl_JoinFilterGraph, + BaseFilterImpl_QueryVendorInfo +}; diff --git a/reactos/dll/directx/quartz/avidec.c b/reactos/dll/directx/quartz/avidec.c index a4f997c9233..0e110d5707d 100644 --- a/reactos/dll/directx/quartz/avidec.c +++ b/reactos/dll/directx/quartz/avidec.c @@ -38,24 +38,37 @@ //#include #include -#include "transform.h" - WINE_DEFAULT_DEBUG_CHANNEL(quartz); typedef struct AVIDecImpl { - TransformFilterImpl tf; + TransformFilter tf; + HIC hvid; BITMAPINFOHEADER* pBihIn; BITMAPINFOHEADER* pBihOut; + REFERENCE_TIME late; } AVIDecImpl; -static HRESULT AVIDec_ProcessBegin(TransformFilterImpl* pTransformFilter) +static const IBaseFilterVtbl AVIDec_Vtbl; + +static inline AVIDecImpl *impl_from_IBaseFilter( IBaseFilter *iface ) { - AVIDecImpl* This = (AVIDecImpl*)pTransformFilter; + return CONTAINING_RECORD(iface, AVIDecImpl, tf.filter.IBaseFilter_iface); +} + +static inline AVIDecImpl *impl_from_TransformFilter( TransformFilter *iface ) +{ + return CONTAINING_RECORD(iface, AVIDecImpl, tf.filter); +} + +static HRESULT WINAPI AVIDec_StartStreaming(TransformFilter* pTransformFilter) +{ + AVIDecImpl* This = impl_from_TransformFilter(pTransformFilter); DWORD result; TRACE("(%p)->()\n", This); + This->late = -1; result = ICDecompressBegin(This->hvid, This->pBihIn, This->pBihOut); if (result != ICERR_OK) @@ -66,9 +79,39 @@ static HRESULT AVIDec_ProcessBegin(TransformFilterImpl* pTransformFilter) return S_OK; } -static HRESULT AVIDec_ProcessSampleData(InputPin *pin, IMediaSample *pSample) +static HRESULT WINAPI AVIDec_EndFlush(TransformFilter *pTransformFilter) { + AVIDecImpl* This = impl_from_TransformFilter(pTransformFilter); + This->late = -1; + return S_OK; +} + +static HRESULT WINAPI AVIDec_NotifyDrop(TransformFilter *pTransformFilter, IBaseFilter *sender, Quality qm) { + AVIDecImpl *This = impl_from_TransformFilter(pTransformFilter); + + EnterCriticalSection(&This->tf.filter.csFilter); + if (qm.Late > 0) + This->late = qm.Late + qm.TimeStamp; + else + This->late = -1; + LeaveCriticalSection(&This->tf.filter.csFilter); + return S_OK; +} + +static int AVIDec_DropSample(AVIDecImpl *This, REFERENCE_TIME tStart) { + if (This->late < 0) + return 0; + + if (tStart < This->late) { + TRACE("Dropping sample\n"); + return 1; + } + This->late = -1; + return 0; +} + +static HRESULT WINAPI AVIDec_Receive(TransformFilter *tf, IMediaSample *pSample) { - AVIDecImpl* This = (AVIDecImpl *)pin->pin.pinInfo.pFilter; + AVIDecImpl* This = impl_from_TransformFilter(tf); AM_MEDIA_TYPE amt; HRESULT hr; DWORD res; @@ -78,20 +121,9 @@ static HRESULT AVIDec_ProcessSampleData(InputPin *pin, IMediaSample *pSample) DWORD cbSrcStream; LPBYTE pbSrcStream; LONGLONG tStart, tStop; + DWORD flags = 0; - EnterCriticalSection(&This->tf.csFilter); - if (This->tf.state == State_Stopped) - { - LeaveCriticalSection(&This->tf.csFilter); - return VFW_E_WRONG_STATE; - } - - if (pin->end_of_stream || pin->flushing) - { - LeaveCriticalSection(&This->tf.csFilter); - return S_FALSE; - } - + EnterCriticalSection(&This->tf.csReceive); hr = IMediaSample_GetPointer(pSample, &pbSrcStream); if (FAILED(hr)) { @@ -112,7 +144,7 @@ static HRESULT AVIDec_ProcessSampleData(InputPin *pin, IMediaSample *pSample) /* Update input size to match sample size */ This->pBihIn->biSizeImage = cbSrcStream; - hr = OutputPin_GetDeliveryBuffer((OutputPin*)This->tf.ppPins[1], &pOutSample, NULL, NULL, 0); + hr = BaseOutputPinImpl_GetDeliveryBuffer((BaseOutputPin*)This->tf.ppPins[1], &pOutSample, NULL, NULL, 0); if (FAILED(hr)) { ERR("Unable to get delivery buffer (%x)\n", hr); goto error; @@ -133,39 +165,59 @@ static HRESULT AVIDec_ProcessSampleData(InputPin *pin, IMediaSample *pSample) goto error; } - res = ICDecompress(This->hvid, 0, This->pBihIn, pbSrcStream, This->pBihOut, pbDstStream); + if (IMediaSample_IsPreroll(pSample) == S_OK) + flags |= ICDECOMPRESS_PREROLL; + if (IMediaSample_IsSyncPoint(pSample) != S_OK) + flags |= ICDECOMPRESS_NOTKEYFRAME; + hr = IMediaSample_GetTime(pSample, &tStart, &tStop); + if (hr == S_OK && AVIDec_DropSample(This, tStart)) + flags |= ICDECOMPRESS_HURRYUP; + + res = ICDecompress(This->hvid, flags, This->pBihIn, pbSrcStream, This->pBihOut, pbDstStream); if (res != ICERR_OK) ERR("Error occurred during the decompression (%x)\n", res); + /* Drop sample if its intended to be dropped */ + if (flags & ICDECOMPRESS_HURRYUP) { + hr = S_OK; + goto error; + } + IMediaSample_SetActualDataLength(pOutSample, This->pBihOut->biSizeImage); IMediaSample_SetPreroll(pOutSample, (IMediaSample_IsPreroll(pSample) == S_OK)); IMediaSample_SetDiscontinuity(pOutSample, (IMediaSample_IsDiscontinuity(pSample) == S_OK)); IMediaSample_SetSyncPoint(pOutSample, (IMediaSample_IsSyncPoint(pSample) == S_OK)); - if (IMediaSample_GetTime(pSample, &tStart, &tStop) == S_OK) + if (hr == S_OK) IMediaSample_SetTime(pOutSample, &tStart, &tStop); + else if (hr == VFW_S_NO_STOP_TIME) + IMediaSample_SetTime(pOutSample, &tStart, NULL); else IMediaSample_SetTime(pOutSample, NULL, NULL); - LeaveCriticalSection(&This->tf.csFilter); - hr = OutputPin_SendSample((OutputPin*)This->tf.ppPins[1], pOutSample); + if (IMediaSample_GetMediaTime(pSample, &tStart, &tStop) == S_OK) + IMediaSample_SetMediaTime(pOutSample, &tStart, &tStop); + else + IMediaSample_SetMediaTime(pOutSample, NULL, NULL); + + LeaveCriticalSection(&This->tf.csReceive); + hr = BaseOutputPinImpl_Deliver((BaseOutputPin*)This->tf.ppPins[1], pOutSample); + EnterCriticalSection(&This->tf.csReceive); if (hr != S_OK && hr != VFW_E_NOT_CONNECTED) ERR("Error sending sample (%x)\n", hr); - IMediaSample_Release(pOutSample); - return hr; error: if (pOutSample) IMediaSample_Release(pOutSample); - LeaveCriticalSection(&This->tf.csFilter); + LeaveCriticalSection(&This->tf.csReceive); return hr; } -static HRESULT AVIDec_ProcessEnd(TransformFilterImpl* pTransformFilter) +static HRESULT WINAPI AVIDec_StopStreaming(TransformFilter* pTransformFilter) { - AVIDecImpl* This = (AVIDecImpl*)pTransformFilter; + AVIDecImpl* This = impl_from_TransformFilter(pTransformFilter); DWORD result; TRACE("(%p)->()\n", This); @@ -182,13 +234,16 @@ static HRESULT AVIDec_ProcessEnd(TransformFilterImpl* pTransformFilter) return S_OK; } -static HRESULT AVIDec_ConnectInput(InputPin *pin, const AM_MEDIA_TYPE * pmt) +static HRESULT WINAPI AVIDec_SetMediaType(TransformFilter *tf, PIN_DIRECTION dir, const AM_MEDIA_TYPE * pmt) { - AVIDecImpl* This = (AVIDecImpl*)pin->pin.pinInfo.pFilter; + AVIDecImpl* This = impl_from_TransformFilter(tf); HRESULT hr = VFW_E_TYPE_NOT_ACCEPTED; TRACE("(%p)->(%p)\n", This, pmt); + if (dir != PINDIR_INPUT) + return S_OK; + /* Check root (GUID w/o FOURCC) */ if ((IsEqualIID(&pmt->majortype, &MEDIATYPE_Video)) && (!memcmp(((const char *)&pmt->subtype)+4, ((const char *)&MEDIATYPE_Video)+4, sizeof(GUID)-4))) @@ -268,9 +323,6 @@ static HRESULT AVIDec_ConnectInput(InputPin *pin, const AM_MEDIA_TYPE * pmt) else assert(0); - /* Update buffer size of media samples in output */ - ((OutputPin*)This->tf.ppPins[1])->allocProps.cbBuffer = This->pBihOut->biSizeImage; - TRACE("Connection accepted\n"); return S_OK; } @@ -283,33 +335,69 @@ failed: return hr; } -static HRESULT AVIDec_Cleanup(InputPin *pin) +static HRESULT WINAPI AVIDec_CompleteConnect(TransformFilter *tf, PIN_DIRECTION dir, IPin *pin) { - AVIDecImpl *This = (AVIDecImpl *)pin->pin.pinInfo.pFilter; + AVIDecImpl* This = impl_from_TransformFilter(tf); - TRACE("(%p)->()\n", This); - - if (This->hvid) - ICClose(This->hvid); - if (This->pBihIn) - CoTaskMemFree(This->pBihIn); - if (This->pBihOut) - CoTaskMemFree(This->pBihOut); - - This->hvid = NULL; - This->pBihIn = NULL; - This->pBihOut = NULL; + TRACE("(%p)\n", This); return S_OK; } -static const TransformFuncsTable AVIDec_FuncsTable = { - AVIDec_ProcessBegin, - AVIDec_ProcessSampleData, - AVIDec_ProcessEnd, +static HRESULT WINAPI AVIDec_BreakConnect(TransformFilter *tf, PIN_DIRECTION dir) +{ + AVIDecImpl *This = impl_from_TransformFilter(tf); + + TRACE("(%p)->()\n", This); + + if (dir == PINDIR_INPUT) + { + if (This->hvid) + ICClose(This->hvid); + if (This->pBihIn) + CoTaskMemFree(This->pBihIn); + if (This->pBihOut) + CoTaskMemFree(This->pBihOut); + + This->hvid = NULL; + This->pBihIn = NULL; + This->pBihOut = NULL; + } + + return S_OK; +} + +static HRESULT WINAPI AVIDec_DecideBufferSize(TransformFilter *tf, IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest) +{ + AVIDecImpl *pAVI = impl_from_TransformFilter(tf); + ALLOCATOR_PROPERTIES actual; + + if (!ppropInputRequest->cbAlign) + ppropInputRequest->cbAlign = 1; + + if (ppropInputRequest->cbBuffer < pAVI->pBihOut->biSizeImage) + ppropInputRequest->cbBuffer = pAVI->pBihOut->biSizeImage; + + if (!ppropInputRequest->cBuffers) + ppropInputRequest->cBuffers = 1; + + return IMemAllocator_SetProperties(pAlloc, ppropInputRequest, &actual); +} + +static const TransformFilterFuncTable AVIDec_FuncsTable = { + AVIDec_DecideBufferSize, + AVIDec_StartStreaming, + AVIDec_Receive, + AVIDec_StopStreaming, NULL, - AVIDec_ConnectInput, - AVIDec_Cleanup + AVIDec_SetMediaType, + AVIDec_CompleteConnect, + AVIDec_BreakConnect, + NULL, + NULL, + AVIDec_EndFlush, + NULL, + AVIDec_NotifyDrop }; HRESULT AVIDec_create(IUnknown * pUnkOuter, LPVOID * ppv) @@ -324,19 +412,35 @@ HRESULT AVIDec_create(IUnknown * pUnkOuter, LPVOID * ppv) if (pUnkOuter) return CLASS_E_NOAGGREGATION; - /* Note: This memory is managed by the transform filter once created */ - This = CoTaskMemAlloc(sizeof(AVIDecImpl)); + hr = TransformFilter_Construct(&AVIDec_Vtbl, sizeof(AVIDecImpl), &CLSID_AVIDec, &AVIDec_FuncsTable, (IBaseFilter**)&This); + + if (FAILED(hr)) + return hr; This->hvid = NULL; This->pBihIn = NULL; This->pBihOut = NULL; - hr = TransformFilter_Create(&(This->tf), &CLSID_AVIDec, &AVIDec_FuncsTable, NULL, NULL, NULL); - - if (FAILED(hr)) - return hr; - *ppv = This; return hr; } + +static const IBaseFilterVtbl AVIDec_Vtbl = +{ + TransformFilterImpl_QueryInterface, + BaseFilterImpl_AddRef, + TransformFilterImpl_Release, + BaseFilterImpl_GetClassID, + TransformFilterImpl_Stop, + TransformFilterImpl_Pause, + TransformFilterImpl_Run, + BaseFilterImpl_GetState, + BaseFilterImpl_SetSyncSource, + BaseFilterImpl_GetSyncSource, + BaseFilterImpl_EnumPins, + TransformFilterImpl_FindPin, + BaseFilterImpl_QueryFilterInfo, + BaseFilterImpl_JoinFilterGraph, + BaseFilterImpl_QueryVendorInfo +}; diff --git a/reactos/dll/directx/quartz/avisplit.c b/reactos/dll/directx/quartz/avisplit.c index ef28e3bb63e..8e673418074 100644 --- a/reactos/dll/directx/quartz/avisplit.c +++ b/reactos/dll/directx/quartz/avisplit.c @@ -30,7 +30,6 @@ */ #include "quartz_private.h" -#include "control_private.h" #include "pin.h" //#include "uuids.h" @@ -101,6 +100,11 @@ struct thread_args { DWORD stream; }; +static inline AVISplitterImpl *impl_from_IMediaSeeking( IMediaSeeking *iface ) +{ + return CONTAINING_RECORD(iface, AVISplitterImpl, Parser.sourceSeeking.IMediaSeeking_iface); +} + /* The threading stuff cries for an explanation * * PullPin starts processing and calls AVISplitter_first_request @@ -284,9 +288,9 @@ static HRESULT AVISplitter_next_request(AVISplitterImpl *This, DWORD streamnumbe static HRESULT AVISplitter_Receive(AVISplitterImpl *This, IMediaSample *sample, DWORD streamnumber) { - Parser_OutputPin *pin = (Parser_OutputPin *)This->Parser.ppPins[1+streamnumber]; + Parser_OutputPin *pin = unsafe_impl_Parser_OutputPin_from_IPin(This->Parser.ppPins[1+streamnumber]); HRESULT hr; - LONGLONG start, stop; + LONGLONG start, stop, rtstart, rtstop; StreamData *stream = &This->streams[streamnumber]; start = pin->dwSamplesProcessed; @@ -309,9 +313,31 @@ static HRESULT AVISplitter_Receive(AVISplitterImpl *This, IMediaSample *sample, stop *= 10000000; stop /= stream->streamheader.dwRate; - IMediaSample_SetTime(sample, &start, &stop); + if (IMediaSample_IsDiscontinuity(sample) == S_OK) { + IPin *victim; + EnterCriticalSection(&This->Parser.filter.csFilter); + pin->pin.pin.tStart = start; + pin->pin.pin.dRate = This->Parser.sourceSeeking.dRate; + hr = IPin_ConnectedTo(&pin->pin.pin.IPin_iface, &victim); + if (hr == S_OK) + { + hr = IPin_NewSegment(victim, start, This->Parser.sourceSeeking.llStop, + This->Parser.sourceSeeking.dRate); + if (hr != S_OK) + FIXME("NewSegment returns %08x\n", hr); + IPin_Release(victim); + } + LeaveCriticalSection(&This->Parser.filter.csFilter); + if (hr != S_OK) + return hr; + } + rtstart = (double)(start - pin->pin.pin.tStart) / pin->pin.pin.dRate; + rtstop = (double)(stop - pin->pin.pin.tStart) / pin->pin.pin.dRate; + hr = IMediaSample_SetMediaTime(sample, &start, &stop); + IMediaSample_SetTime(sample, &rtstart, &rtstop); + IMediaSample_SetMediaTime(sample, &start, &stop); - hr = OutputPin_SendSample(&pin->pin, sample); + hr = BaseOutputPinImpl_Deliver(&pin->pin, sample); /* Uncomment this if you want to debug the time differences between the * different streams, it is useful for that @@ -373,7 +399,7 @@ static HRESULT AVISplitter_Sample(LPVOID iface, IMediaSample * pSample, DWORD_PT return S_OK; } - /* Send the sample to whatever thread is appropiate + /* Send the sample to whatever thread is appropriate * That thread should also not have a sample queued at the moment */ /* Debugging */ @@ -421,6 +447,9 @@ static HRESULT AVISplitter_first_request(LPVOID iface) stream->pos_next = stream->pos; stream->index_next = stream->index; + /* This was sent after stopped->paused or stopped->playing, so set seek */ + stream->seek = 1; + /* There should be a packet queued from AVISplitter_next_request last time * It needs to be done now because this is the only way to ensure that every * stream will have at least 1 packet processed @@ -530,13 +559,13 @@ static HRESULT AVISplitter_ProcessIndex(AVISplitterImpl *This, AVISTDINDEX **ind if (!pIndex) return E_OUTOFMEMORY; - IAsyncReader_SyncRead(((PullPin *)This->Parser.ppPins[0])->pReader, qwOffset, cb, (BYTE *)pIndex); + IAsyncReader_SyncRead((impl_PullPin_from_IPin(This->Parser.ppPins[0]))->pReader, qwOffset, cb, (BYTE *)pIndex); rest = cb - sizeof(AVISUPERINDEX) + sizeof(RIFFCHUNK) + sizeof(pIndex->aIndex); TRACE("FOURCC: %s\n", debugstr_an((char *)&pIndex->fcc, 4)); TRACE("wLongsPerEntry: %hd\n", pIndex->wLongsPerEntry); - TRACE("bIndexSubType: %hd\n", pIndex->bIndexSubType); - TRACE("bIndexType: %hd\n", pIndex->bIndexType); + TRACE("bIndexSubType: %u\n", pIndex->bIndexSubType); + TRACE("bIndexType: %u\n", pIndex->bIndexType); TRACE("nEntriesInUse: %u\n", pIndex->nEntriesInUse); TRACE("dwChunkId: %.4s\n", (char *)&pIndex->dwChunkId); TRACE("qwBaseOffset: %x%08x\n", (DWORD)(pIndex->qwBaseOffset >> 32), (DWORD)pIndex->qwBaseOffset); @@ -785,8 +814,8 @@ static HRESULT AVISplitter_ProcessStreamList(AVISplitterImpl * This, const BYTE } TRACE("wLongsPerEntry: %hd\n", pIndex->wLongsPerEntry); - TRACE("bIndexSubType: %hd\n", pIndex->bIndexSubType); - TRACE("bIndexType: %hd\n", pIndex->bIndexType); + TRACE("bIndexSubType: %u\n", pIndex->bIndexSubType); + TRACE("bIndexType: %u\n", pIndex->bIndexType); TRACE("nEntriesInUse: %u\n", pIndex->nEntriesInUse); TRACE("dwChunkId: %.4s\n", (const char *)&pIndex->dwChunkId); if (pIndex->dwReserved[0]) @@ -899,7 +928,7 @@ static HRESULT AVISplitter_InitializeStreams(AVISplitterImpl *This) nMax = This->oldindex->cb / sizeof(This->oldindex->aIndex[0]); - /* Ok, maybe this is more of an excercise to see if I interpret everything correctly or not, but that is useful for now. */ + /* Ok, maybe this is more of an exercise to see if I interpret everything correctly or not, but that is useful for now. */ for (n = 0; n < nMax; ++n) { DWORD streamId = StreamFromFOURCC(This->oldindex->aIndex[n].dwChunkId); @@ -970,16 +999,16 @@ static HRESULT AVISplitter_InitializeStreams(AVISplitterImpl *This) frames *= stream->streamheader.dwScale; /* Keep accuracy as high as possible for duration */ - This->Parser.mediaSeeking.llDuration = frames * 10000000; - This->Parser.mediaSeeking.llDuration /= stream->streamheader.dwRate; - This->Parser.mediaSeeking.llStop = This->Parser.mediaSeeking.llDuration; - This->Parser.mediaSeeking.llCurrent = 0; + This->Parser.sourceSeeking.llDuration = frames * 10000000; + This->Parser.sourceSeeking.llDuration /= stream->streamheader.dwRate; + This->Parser.sourceSeeking.llStop = This->Parser.sourceSeeking.llDuration; + This->Parser.sourceSeeking.llCurrent = 0; frames /= stream->streamheader.dwRate; TRACE("Duration: %d days, %d hours, %d minutes and %d.%03u seconds\n", (DWORD)(frames / 86400), (DWORD)((frames % 86400) / 3600), (DWORD)((frames % 3600) / 60), (DWORD)(frames % 60), - (DWORD)(This->Parser.mediaSeeking.llDuration/10000) % 1000); + (DWORD)(This->Parser.sourceSeeking.llDuration/10000) % 1000); } return S_OK; @@ -990,7 +1019,7 @@ static HRESULT AVISplitter_Disconnect(LPVOID iface); /* FIXME: fix leaks on failure here */ static HRESULT AVISplitter_InputPin_PreConnect(IPin * iface, IPin * pConnectPin, ALLOCATOR_PROPERTIES *props) { - PullPin *This = (PullPin *)iface; + PullPin *This = impl_PullPin_from_IPin(iface); HRESULT hr; RIFFLIST list; LONGLONG pos = 0; /* in bytes */ @@ -1239,7 +1268,7 @@ static ULONG WINAPI AVISplitter_Release(IBaseFilter *iface) AVISplitterImpl *This = (AVISplitterImpl *)iface; ULONG ref; - ref = InterlockedDecrement(&This->Parser.refCount); + ref = InterlockedDecrement(&This->Parser.filter.refCount); TRACE("(%p)->() Release from %d\n", This, ref + 1); @@ -1252,15 +1281,15 @@ static ULONG WINAPI AVISplitter_Release(IBaseFilter *iface) return ref; } -static HRESULT AVISplitter_seek(IBaseFilter *iface) +static HRESULT WINAPI AVISplitter_seek(IMediaSeeking *iface) { - AVISplitterImpl *This = (AVISplitterImpl *)iface; + AVISplitterImpl *This = impl_from_IMediaSeeking(iface); PullPin *pPin = This->Parser.pInputPin; LONGLONG newpos, endpos; DWORD x; - newpos = This->Parser.mediaSeeking.llCurrent; - endpos = This->Parser.mediaSeeking.llDuration; + newpos = This->Parser.sourceSeeking.llCurrent; + endpos = This->Parser.sourceSeeking.llDuration; if (newpos > endpos) { @@ -1272,15 +1301,14 @@ static HRESULT AVISplitter_seek(IBaseFilter *iface) EnterCriticalSection(&pPin->thread_lock); /* Send a flush to all output pins */ - IPin_BeginFlush((IPin *)pPin); + IPin_BeginFlush(&pPin->pin.IPin_iface); /* Make sure this is done while stopped, BeginFlush takes care of this */ - EnterCriticalSection(&This->Parser.csFilter); + EnterCriticalSection(&This->Parser.filter.csFilter); for (x = 0; x < This->Parser.cStreams; ++x) { - Parser_OutputPin *pin = (Parser_OutputPin *)This->Parser.ppPins[1+x]; + Parser_OutputPin *pin = unsafe_impl_Parser_OutputPin_from_IPin(This->Parser.ppPins[1+x]); StreamData *stream = This->streams + x; - IPin *victim = NULL; LONGLONG wanted_frames; DWORD last_keyframe = 0, last_keyframeidx = 0, preroll = 0; @@ -1289,13 +1317,6 @@ static HRESULT AVISplitter_seek(IBaseFilter *iface) wanted_frames /= 10000000; wanted_frames /= stream->streamheader.dwScale; - IPin_ConnectedTo((IPin *)pin, &victim); - if (victim) - { - IPin_NewSegment(victim, newpos, endpos, pPin->dRate); - IPin_Release(victim); - } - pin->dwSamplesProcessed = 0; stream->index = 0; stream->pos = 0; @@ -1377,10 +1398,10 @@ static HRESULT AVISplitter_seek(IBaseFilter *iface) stream->preroll = preroll; stream->seek = 1; } - LeaveCriticalSection(&This->Parser.csFilter); + LeaveCriticalSection(&This->Parser.filter.csFilter); TRACE("Done flushing\n"); - IPin_EndFlush((IPin *)pPin); + IPin_EndFlush(&pPin->pin.IPin_iface); LeaveCriticalSection(&pPin->thread_lock); return S_OK; diff --git a/reactos/dll/directx/quartz/control.c b/reactos/dll/directx/quartz/control.c deleted file mode 100644 index 03f87bbe6dc..00000000000 --- a/reactos/dll/directx/quartz/control.c +++ /dev/null @@ -1,921 +0,0 @@ -/* - * Filter Seeking and Control Interfaces - * - * Copyright 2003 Robert Shearman - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ -/* FIXME: critical sections */ - -#include "quartz_private.h" -#include "control_private.h" - -//#include "uuids.h" -#include - -#include - -WINE_DEFAULT_DEBUG_CHANNEL(quartz); - -static const IMediaSeekingVtbl IMediaSeekingPassThru_Vtbl; - -typedef struct PassThruImpl { - const ISeekingPassThruVtbl *IPassThru_vtbl; - const IUnknownVtbl *IInner_vtbl; - const IMediaSeekingVtbl *IMediaSeeking_vtbl; - - LONG ref; - IUnknown * pUnkOuter; - IPin * pin; - BOOL bUnkOuterValid; - BOOL bAggregatable; - BOOL renderer; -} PassThruImpl; - -static HRESULT WINAPI SeekInner_QueryInterface(IUnknown * iface, - REFIID riid, - LPVOID *ppvObj) { - ICOM_THIS_MULTI(PassThruImpl, IInner_vtbl, iface); - TRACE("(%p)->(%s (%p), %p)\n", This, debugstr_guid(riid), riid, ppvObj); - - if (This->bAggregatable) - This->bUnkOuterValid = TRUE; - - if (IsEqualGUID(&IID_IUnknown, riid)) - { - *ppvObj = &(This->IInner_vtbl); - TRACE(" returning IUnknown interface (%p)\n", *ppvObj); - } else if (IsEqualGUID(&IID_ISeekingPassThru, riid)) { - *ppvObj = &(This->IPassThru_vtbl); - TRACE(" returning ISeekingPassThru interface (%p)\n", *ppvObj); - } else if (IsEqualGUID(&IID_IMediaSeeking, riid)) { - *ppvObj = &(This->IMediaSeeking_vtbl); - TRACE(" returning IMediaSeeking interface (%p)\n", *ppvObj); - } else { - *ppvObj = NULL; - FIXME("unknown interface %s\n", debugstr_guid(riid)); - return E_NOINTERFACE; - } - - IUnknown_AddRef((IUnknown *)(*ppvObj)); - return S_OK; -} - -static ULONG WINAPI SeekInner_AddRef(IUnknown * iface) { - ICOM_THIS_MULTI(PassThruImpl, IInner_vtbl, iface); - ULONG ref = InterlockedIncrement(&This->ref); - - TRACE("(%p)->(): new ref = %d\n", This, ref); - - return ref; -} - -static ULONG WINAPI SeekInner_Release(IUnknown * iface) { - ICOM_THIS_MULTI(PassThruImpl, IInner_vtbl, iface); - ULONG ref = InterlockedDecrement(&This->ref); - - TRACE("(%p)->(): new ref = %d\n", This, ref); - - if (ref == 0) - { - CoTaskMemFree(This); - } - return ref; -} - -static const IUnknownVtbl IInner_VTable = -{ - SeekInner_QueryInterface, - SeekInner_AddRef, - SeekInner_Release -}; - -/* Generic functions for aggregation */ -static HRESULT SeekOuter_QueryInterface(PassThruImpl *This, REFIID riid, LPVOID *ppv) -{ - if (This->bAggregatable) - This->bUnkOuterValid = TRUE; - - if (This->pUnkOuter) - { - if (This->bAggregatable) - return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv); - - if (IsEqualIID(riid, &IID_IUnknown)) - { - HRESULT hr; - - IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl)); - hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv); - IUnknown_Release((IUnknown *)&(This->IInner_vtbl)); - This->bAggregatable = TRUE; - return hr; - } - - *ppv = NULL; - return E_NOINTERFACE; - } - - return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv); -} - -static ULONG SeekOuter_AddRef(PassThruImpl *This) -{ - if (This->pUnkOuter && This->bUnkOuterValid) - return IUnknown_AddRef(This->pUnkOuter); - return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl)); -} - -static ULONG SeekOuter_Release(PassThruImpl *This) -{ - if (This->pUnkOuter && This->bUnkOuterValid) - return IUnknown_Release(This->pUnkOuter); - return IUnknown_Release((IUnknown *)&(This->IInner_vtbl)); -} - -static HRESULT WINAPI SeekingPassThru_QueryInterface(ISeekingPassThru *iface, REFIID riid, LPVOID *ppvObj) -{ - ICOM_THIS_MULTI(PassThruImpl, IPassThru_vtbl, iface); - - TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); - - return SeekOuter_QueryInterface(This, riid, ppvObj); -} - -static ULONG WINAPI SeekingPassThru_AddRef(ISeekingPassThru *iface) -{ - ICOM_THIS_MULTI(PassThruImpl, IPassThru_vtbl, iface); - - TRACE("(%p/%p)->()\n", This, iface); - - return SeekOuter_AddRef(This); -} - -static ULONG WINAPI SeekingPassThru_Release(ISeekingPassThru *iface) -{ - ICOM_THIS_MULTI(PassThruImpl, IPassThru_vtbl, iface); - - TRACE("(%p/%p)->()\n", This, iface); - - return SeekOuter_Release(This); -} - -static HRESULT WINAPI SeekingPassThru_Init(ISeekingPassThru *iface, BOOL renderer, IPin *pin) -{ - ICOM_THIS_MULTI(PassThruImpl, IPassThru_vtbl, iface); - - TRACE("(%p/%p)->(%d, %p)\n", This, iface, renderer, pin); - - if (This->pin) - FIXME("Re-initializing?\n"); - - This->renderer = renderer; - This->pin = pin; - - return S_OK; -} - -static const ISeekingPassThruVtbl ISeekingPassThru_Vtbl = -{ - SeekingPassThru_QueryInterface, - SeekingPassThru_AddRef, - SeekingPassThru_Release, - SeekingPassThru_Init -}; - -HRESULT SeekingPassThru_create(IUnknown *pUnkOuter, LPVOID *ppObj) -{ - PassThruImpl *fimpl; - - TRACE("(%p,%p)\n", pUnkOuter, ppObj); - - *ppObj = fimpl = CoTaskMemAlloc(sizeof(*fimpl)); - if (!fimpl) - return E_OUTOFMEMORY; - - fimpl->pUnkOuter = pUnkOuter; - fimpl->bUnkOuterValid = FALSE; - fimpl->bAggregatable = FALSE; - fimpl->IInner_vtbl = &IInner_VTable; - fimpl->IPassThru_vtbl = &ISeekingPassThru_Vtbl; - fimpl->IMediaSeeking_vtbl = &IMediaSeekingPassThru_Vtbl; - fimpl->ref = 1; - fimpl->pin = NULL; - return S_OK; -} - -typedef HRESULT (*SeekFunc)( IMediaSeeking *to, LPVOID arg ); - -static HRESULT ForwardCmdSeek( PCRITICAL_SECTION crit_sect, IBaseFilter* from, SeekFunc fnSeek, LPVOID arg ) -{ - HRESULT hr = S_OK; - HRESULT hr_return = S_OK; - IEnumPins *enumpins = NULL; - BOOL foundend = FALSE, allnotimpl = TRUE; - - hr = IBaseFilter_EnumPins( from, &enumpins ); - if (FAILED(hr)) - goto out; - - hr = IEnumPins_Reset( enumpins ); - while (hr == S_OK) { - IPin *pin = NULL; - hr = IEnumPins_Next( enumpins, 1, &pin, NULL ); - if (hr == VFW_E_ENUM_OUT_OF_SYNC) - { - hr = IEnumPins_Reset( enumpins ); - continue; - } - if (pin) - { - PIN_DIRECTION dir; - - IPin_QueryDirection( pin, &dir ); - if (dir == PINDIR_INPUT) - { - IPin *connected = NULL; - - IPin_ConnectedTo( pin, &connected ); - if (connected) - { - HRESULT hr_local; - IMediaSeeking *seek = NULL; - - hr_local = IPin_QueryInterface( connected, &IID_IMediaSeeking, (void**)&seek ); - if (hr_local == S_OK) - { - foundend = TRUE; - if (crit_sect) - { - LeaveCriticalSection( crit_sect ); - hr_local = fnSeek( seek , arg ); - EnterCriticalSection( crit_sect ); - } - else - hr_local = fnSeek( seek , arg ); - - if (hr_local != E_NOTIMPL) - allnotimpl = FALSE; - - hr_return = updatehres( hr_return, hr_local ); - IMediaSeeking_Release( seek ); - } - IPin_Release(connected); - } - } - IPin_Release( pin ); - } - } - IEnumPins_Release( enumpins ); - - if (foundend && allnotimpl) - hr = E_NOTIMPL; - else - hr = hr_return; - -out: - TRACE("Returning: %08x\n", hr); - return hr; -} - - -HRESULT MediaSeekingImpl_Init(IBaseFilter *pUserData, CHANGEPROC fnChangeStop, CHANGEPROC fnChangeCurrent, CHANGEPROC fnChangeRate, MediaSeekingImpl * pSeeking, PCRITICAL_SECTION crit_sect) -{ - assert(fnChangeStop && fnChangeCurrent && fnChangeRate); - - pSeeking->refCount = 1; - pSeeking->pUserData = pUserData; - pSeeking->fnChangeRate = fnChangeRate; - pSeeking->fnChangeStop = fnChangeStop; - pSeeking->fnChangeCurrent = fnChangeCurrent; - pSeeking->dwCapabilities = AM_SEEKING_CanSeekForwards | - AM_SEEKING_CanSeekBackwards | - AM_SEEKING_CanSeekAbsolute | - AM_SEEKING_CanGetStopPos | - AM_SEEKING_CanGetDuration; - pSeeking->llCurrent = 0; - pSeeking->llStop = ((ULONGLONG)0x80000000) << 32; - pSeeking->llDuration = pSeeking->llStop; - pSeeking->dRate = 1.0; - pSeeking->timeformat = TIME_FORMAT_MEDIA_TIME; - pSeeking->crst = crit_sect; - - return S_OK; -} - -struct pos_args { - LONGLONG* current, *stop; - DWORD curflags, stopflags; -}; - -static HRESULT fwd_setposition(IMediaSeeking *seek, LPVOID pargs) -{ - struct pos_args *args = (void*)pargs; - - return IMediaSeeking_SetPositions(seek, args->current, args->curflags, args->stop, args->stopflags); -} - -static HRESULT fwd_checkcaps(IMediaSeeking *iface, LPVOID pcaps) -{ - DWORD *caps = pcaps; - return IMediaSeeking_CheckCapabilities(iface, caps); -} - -static HRESULT fwd_settimeformat(IMediaSeeking *iface, LPVOID pformat) -{ - const GUID *format = pformat; - return IMediaSeeking_SetTimeFormat(iface, format); -} - -static HRESULT fwd_getduration(IMediaSeeking *iface, LPVOID pdur) -{ - LONGLONG *duration = pdur; - LONGLONG mydur = *duration; - HRESULT hr; - - hr = IMediaSeeking_GetDuration(iface, &mydur); - if (FAILED(hr)) - return hr; - - if ((mydur < *duration) || (*duration < 0 && mydur > 0)) - *duration = mydur; - return hr; -} - -static HRESULT fwd_getstopposition(IMediaSeeking *iface, LPVOID pdur) -{ - LONGLONG *duration = pdur; - LONGLONG mydur = *duration; - HRESULT hr; - - hr = IMediaSeeking_GetStopPosition(iface, &mydur); - if (FAILED(hr)) - return hr; - - if ((mydur < *duration) || (*duration < 0 && mydur > 0)) - *duration = mydur; - return hr; -} - -static HRESULT fwd_getcurposition(IMediaSeeking *iface, LPVOID pdur) -{ - LONGLONG *duration = pdur; - LONGLONG mydur = *duration; - HRESULT hr; - - hr = IMediaSeeking_GetCurrentPosition(iface, &mydur); - if (FAILED(hr)) - return hr; - - if ((mydur < *duration) || (*duration < 0 && mydur > 0)) - *duration = mydur; - return hr; -} - -static HRESULT fwd_setrate(IMediaSeeking *iface, LPVOID prate) -{ - double *rate = prate; - - HRESULT hr; - - hr = IMediaSeeking_SetRate(iface, *rate); - if (FAILED(hr)) - return hr; - - return hr; -} - - -HRESULT WINAPI MediaSeekingImpl_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities) -{ - MediaSeekingImpl *This = (MediaSeekingImpl *)iface; - - TRACE("(%p)\n", pCapabilities); - - *pCapabilities = This->dwCapabilities; - - return S_OK; -} - -HRESULT WINAPI MediaSeekingImpl_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities) -{ - MediaSeekingImpl *This = (MediaSeekingImpl *)iface; - HRESULT hr; - DWORD dwCommonCaps; - - TRACE("(%p)\n", pCapabilities); - - if (!pCapabilities) - return E_POINTER; - - EnterCriticalSection(This->crst); - hr = ForwardCmdSeek(This->crst, This->pUserData, fwd_checkcaps, pCapabilities); - LeaveCriticalSection(This->crst); - if (FAILED(hr) && hr != E_NOTIMPL) - return hr; - - dwCommonCaps = *pCapabilities & This->dwCapabilities; - - if (!dwCommonCaps) - hr = E_FAIL; - else - hr = (*pCapabilities == dwCommonCaps) ? S_OK : S_FALSE; - *pCapabilities = dwCommonCaps; - - return hr; -} - -HRESULT WINAPI MediaSeekingImpl_IsFormatSupported(IMediaSeeking * iface, const GUID * pFormat) -{ - TRACE("(%s)\n", qzdebugstr_guid(pFormat)); - - return (IsEqualIID(pFormat, &TIME_FORMAT_MEDIA_TIME) ? S_OK : S_FALSE); -} - -HRESULT WINAPI MediaSeekingImpl_QueryPreferredFormat(IMediaSeeking * iface, GUID * pFormat) -{ - TRACE("(%s)\n", qzdebugstr_guid(pFormat)); - - *pFormat = TIME_FORMAT_MEDIA_TIME; - return S_OK; -} - -HRESULT WINAPI MediaSeekingImpl_GetTimeFormat(IMediaSeeking * iface, GUID * pFormat) -{ - MediaSeekingImpl *This = (MediaSeekingImpl *)iface; - TRACE("(%s)\n", qzdebugstr_guid(pFormat)); - - EnterCriticalSection(This->crst); - *pFormat = This->timeformat; - LeaveCriticalSection(This->crst); - - return S_OK; -} - -HRESULT WINAPI MediaSeekingImpl_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat) -{ - MediaSeekingImpl *This = (MediaSeekingImpl *)iface; - HRESULT hr = S_OK; - - TRACE("(%s)\n", qzdebugstr_guid(pFormat)); - - EnterCriticalSection(This->crst); - if (!IsEqualIID(pFormat, &This->timeformat)) - hr = S_FALSE; - LeaveCriticalSection(This->crst); - - return hr; -} - - -HRESULT WINAPI MediaSeekingImpl_SetTimeFormat(IMediaSeeking * iface, const GUID * pFormat) -{ - MediaSeekingImpl *This = (MediaSeekingImpl *)iface; - TRACE("(%s)\n", qzdebugstr_guid(pFormat)); - - EnterCriticalSection(This->crst); - ForwardCmdSeek(This->crst, This->pUserData, fwd_settimeformat, (LPVOID)pFormat); - LeaveCriticalSection(This->crst); - - return (IsEqualIID(pFormat, &TIME_FORMAT_MEDIA_TIME) ? S_OK : S_FALSE); -} - - -HRESULT WINAPI MediaSeekingImpl_GetDuration(IMediaSeeking * iface, LONGLONG * pDuration) -{ - MediaSeekingImpl *This = (MediaSeekingImpl *)iface; - - TRACE("(%p)\n", pDuration); - - EnterCriticalSection(This->crst); - *pDuration = This->llDuration; - ForwardCmdSeek(This->crst, This->pUserData, fwd_getduration, pDuration); - LeaveCriticalSection(This->crst); - - return S_OK; -} - -HRESULT WINAPI MediaSeekingImpl_GetStopPosition(IMediaSeeking * iface, LONGLONG * pStop) -{ - MediaSeekingImpl *This = (MediaSeekingImpl *)iface; - - TRACE("(%p)\n", pStop); - - EnterCriticalSection(This->crst); - *pStop = This->llStop; - ForwardCmdSeek(This->crst, This->pUserData, fwd_getstopposition, pStop); - LeaveCriticalSection(This->crst); - - return S_OK; -} - -/* FIXME: Make use of the info the filter should expose */ -HRESULT WINAPI MediaSeekingImpl_GetCurrentPosition(IMediaSeeking * iface, LONGLONG * pCurrent) -{ - MediaSeekingImpl *This = (MediaSeekingImpl *)iface; - - TRACE("(%p)\n", pCurrent); - - EnterCriticalSection(This->crst); - *pCurrent = This->llCurrent; - ForwardCmdSeek(This->crst, This->pUserData, fwd_getcurposition, pCurrent); - LeaveCriticalSection(This->crst); - - return S_OK; -} - -HRESULT WINAPI MediaSeekingImpl_ConvertTimeFormat(IMediaSeeking * iface, LONGLONG * pTarget, const GUID * pTargetFormat, LONGLONG Source, const GUID * pSourceFormat) -{ - if (IsEqualIID(pTargetFormat, &TIME_FORMAT_MEDIA_TIME) && IsEqualIID(pSourceFormat, &TIME_FORMAT_MEDIA_TIME)) - { - *pTarget = Source; - return S_OK; - } - /* FIXME: clear pTarget? */ - return E_INVALIDARG; -} - -static inline LONGLONG Adjust(LONGLONG value, const LONGLONG * pModifier, DWORD dwFlags) -{ - switch (dwFlags & AM_SEEKING_PositioningBitsMask) - { - case AM_SEEKING_NoPositioning: - return value; - case AM_SEEKING_AbsolutePositioning: - return *pModifier; - case AM_SEEKING_RelativePositioning: - case AM_SEEKING_IncrementalPositioning: - return value + *pModifier; - default: - assert(FALSE); - return 0; - } -} - -HRESULT WINAPI MediaSeekingImpl_SetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, DWORD dwCurrentFlags, LONGLONG * pStop, DWORD dwStopFlags) -{ - MediaSeekingImpl *This = (MediaSeekingImpl *)iface; - BOOL bChangeCurrent = FALSE, bChangeStop = FALSE; - LONGLONG llNewCurrent, llNewStop; - struct pos_args args; - - TRACE("(%p, %x, %p, %x)\n", pCurrent, dwCurrentFlags, pStop, dwStopFlags); - - args.current = pCurrent; - args.stop = pStop; - args.curflags = dwCurrentFlags; - args.stopflags = dwStopFlags; - - EnterCriticalSection(This->crst); - - llNewCurrent = Adjust(This->llCurrent, pCurrent, dwCurrentFlags); - llNewStop = Adjust(This->llStop, pStop, dwStopFlags); - - if (pCurrent) - bChangeCurrent = TRUE; - if (llNewStop != This->llStop) - bChangeStop = TRUE; - - TRACE("Old: %u, New: %u\n", (DWORD)(This->llCurrent/10000000), (DWORD)(llNewCurrent/10000000)); - - This->llCurrent = llNewCurrent; - This->llStop = llNewStop; - - if (pCurrent && (dwCurrentFlags & AM_SEEKING_ReturnTime)) - *pCurrent = llNewCurrent; - if (pStop && (dwStopFlags & AM_SEEKING_ReturnTime)) - *pStop = llNewStop; - - ForwardCmdSeek(This->crst, This->pUserData, fwd_setposition, &args); - LeaveCriticalSection(This->crst); - - if (bChangeCurrent) - This->fnChangeCurrent(This->pUserData); - if (bChangeStop) - This->fnChangeStop(This->pUserData); - - return S_OK; -} - -HRESULT WINAPI MediaSeekingImpl_GetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, LONGLONG * pStop) -{ - MediaSeekingImpl *This = (MediaSeekingImpl *)iface; - - TRACE("(%p, %p)\n", pCurrent, pStop); - - EnterCriticalSection(This->crst); - *pCurrent = This->llCurrent; - *pStop = This->llStop; - LeaveCriticalSection(This->crst); - - return S_OK; -} - -HRESULT WINAPI MediaSeekingImpl_GetAvailable(IMediaSeeking * iface, LONGLONG * pEarliest, LONGLONG * pLatest) -{ - MediaSeekingImpl *This = (MediaSeekingImpl *)iface; - - TRACE("(%p, %p)\n", pEarliest, pLatest); - - EnterCriticalSection(This->crst); - *pEarliest = 0; - *pLatest = This->llDuration; - LeaveCriticalSection(This->crst); - - return S_OK; -} - -HRESULT WINAPI MediaSeekingImpl_SetRate(IMediaSeeking * iface, double dRate) -{ - MediaSeekingImpl *This = (MediaSeekingImpl *)iface; - BOOL bChangeRate = (dRate != This->dRate); - HRESULT hr = S_OK; - - TRACE("(%e)\n", dRate); - - if (dRate > 100 || dRate < .001) - { - FIXME("Excessive rate %e, ignoring\n", dRate); - return VFW_E_UNSUPPORTED_AUDIO; - } - - EnterCriticalSection(This->crst); - This->dRate = dRate; - if (bChangeRate) - hr = This->fnChangeRate(This->pUserData); - ForwardCmdSeek(This->crst, This->pUserData, fwd_setrate, &dRate); - LeaveCriticalSection(This->crst); - - return hr; -} - -HRESULT WINAPI MediaSeekingImpl_GetRate(IMediaSeeking * iface, double * dRate) -{ - MediaSeekingImpl *This = (MediaSeekingImpl *)iface; - - TRACE("(%p)\n", dRate); - - EnterCriticalSection(This->crst); - /* Forward? */ - *dRate = This->dRate; - LeaveCriticalSection(This->crst); - - return S_OK; -} - -HRESULT WINAPI MediaSeekingImpl_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll) -{ - TRACE("(%p)\n", pPreroll); - - *pPreroll = 0; - return S_OK; -} - -static HRESULT WINAPI MediaSeekingPassThru_QueryInterface(IMediaSeeking *iface, REFIID riid, LPVOID *ppvObj) -{ - ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface); - - TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); - - return SeekOuter_QueryInterface(This, riid, ppvObj); -} - -static ULONG WINAPI MediaSeekingPassThru_AddRef(IMediaSeeking *iface) -{ - ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface); - - TRACE("(%p/%p)->()\n", iface, This); - - return SeekOuter_AddRef(This); -} - -static ULONG WINAPI MediaSeekingPassThru_Release(IMediaSeeking *iface) -{ - ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface); - - TRACE("(%p/%p)->()\n", iface, This); - - return SeekOuter_Release(This); -} - -static HRESULT WINAPI MediaSeekingPassThru_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities) -{ - ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface); - - TRACE("(%p/%p)->(%p)\n", iface, This, pCapabilities); - - FIXME("stub\n"); - return E_NOTIMPL; -} - -static HRESULT WINAPI MediaSeekingPassThru_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities) -{ - ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface); - - TRACE("(%p/%p)->(%p)\n", iface, This, pCapabilities); - - if (!pCapabilities) - return E_POINTER; - - FIXME("stub\n"); - return E_NOTIMPL; -} - -static HRESULT WINAPI MediaSeekingPassThru_IsFormatSupported(IMediaSeeking * iface, const GUID * pFormat) -{ - ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface); - TRACE("(%p/%p)->(%s)\n", iface, This, qzdebugstr_guid(pFormat)); - - FIXME("stub\n"); - return E_NOTIMPL; -} - -static HRESULT WINAPI MediaSeekingPassThru_QueryPreferredFormat(IMediaSeeking * iface, GUID * pFormat) -{ - ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface); - TRACE("(%p/%p)->(%p)\n", iface, This, pFormat); - - FIXME("stub\n"); - return E_NOTIMPL; -} - -static HRESULT WINAPI MediaSeekingPassThru_GetTimeFormat(IMediaSeeking * iface, GUID * pFormat) -{ - ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface); - TRACE("(%p/%p)->(%p)\n", iface, This, pFormat); - - FIXME("stub\n"); - return E_NOTIMPL; -} - -static HRESULT WINAPI MediaSeekingPassThru_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat) -{ - ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface); - - TRACE("(%p/%p)->(%s)\n", iface, This, qzdebugstr_guid(pFormat)); - - FIXME("stub\n"); - return E_NOTIMPL; -} - - -static HRESULT WINAPI MediaSeekingPassThru_SetTimeFormat(IMediaSeeking * iface, const GUID * pFormat) -{ - ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface); - TRACE("(%p/%p)->(%s)\n", iface, This, qzdebugstr_guid(pFormat)); - - FIXME("stub\n"); - return E_NOTIMPL; -} - - -static HRESULT WINAPI MediaSeekingPassThru_GetDuration(IMediaSeeking * iface, LONGLONG * pDuration) -{ - ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface); - PIN_INFO info; - HRESULT hr; - - TRACE("(%p/%p)->(%p)\n", iface, This, pDuration); - - IPin_QueryPinInfo(This->pin, &info); - - hr = ForwardCmdSeek(NULL, info.pFilter, fwd_getduration, pDuration); - IBaseFilter_Release(info.pFilter); - - return hr; -} - -static HRESULT WINAPI MediaSeekingPassThru_GetStopPosition(IMediaSeeking * iface, LONGLONG * pStop) -{ - ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface); - - TRACE("(%p/%p)->(%p)\n", iface, This, pStop); - - FIXME("stub\n"); - return E_NOTIMPL; -} - -/* FIXME: Make use of the info the filter should expose */ -static HRESULT WINAPI MediaSeekingPassThru_GetCurrentPosition(IMediaSeeking * iface, LONGLONG * pCurrent) -{ - ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface); - - TRACE("(%p/%p)->(%p)\n", iface, This, pCurrent); - - FIXME("stub\n"); - return E_NOTIMPL; -} - -static HRESULT WINAPI MediaSeekingPassThru_ConvertTimeFormat(IMediaSeeking * iface, LONGLONG * pTarget, const GUID * pTargetFormat, LONGLONG Source, const GUID * pSourceFormat) -{ - ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface); - - TRACE("(%p/%p)->(%p,%s,%x%08x,%s)\n", iface, This, pTarget, debugstr_guid(pTargetFormat), (DWORD)(Source>>32), (DWORD)Source, debugstr_guid(pSourceFormat)); - - FIXME("stub\n"); - return E_NOTIMPL; -} - -static HRESULT WINAPI MediaSeekingPassThru_SetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, DWORD dwCurrentFlags, LONGLONG * pStop, DWORD dwStopFlags) -{ - ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface); - struct pos_args args; - PIN_INFO info; - HRESULT hr; - - TRACE("(%p/%p)->(%p, %p)\n", iface, This, pCurrent, pStop); - args.current = pCurrent; - args.stop = pStop; - args.curflags = dwCurrentFlags; - args.stopflags = dwStopFlags; - - IPin_QueryPinInfo(This->pin, &info); - - hr = ForwardCmdSeek(NULL, info.pFilter, fwd_setposition, &args); - IBaseFilter_Release(info.pFilter); - return hr; -} - -static HRESULT WINAPI MediaSeekingPassThru_GetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, LONGLONG * pStop) -{ - ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface); - - TRACE("(%p/%p)->(%p, %p)\n", iface, This, pCurrent, pStop); - - FIXME("stub\n"); - return E_NOTIMPL; -} - -static HRESULT WINAPI MediaSeekingPassThru_GetAvailable(IMediaSeeking * iface, LONGLONG * pEarliest, LONGLONG * pLatest) -{ - ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface); - - TRACE("(%p/%p)->(%p,%p)\n", iface, This, pEarliest, pLatest); - - FIXME("stub\n"); - return E_NOTIMPL; -} - -static HRESULT WINAPI MediaSeekingPassThru_SetRate(IMediaSeeking * iface, double dRate) -{ - ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface); - - TRACE("(%p/%p)->(%e)\n", iface, This, dRate); - - FIXME("stub\n"); - return E_NOTIMPL; -} - -static HRESULT WINAPI MediaSeekingPassThru_GetRate(IMediaSeeking * iface, double * dRate) -{ - ICOM_THIS_MULTI(PassThruImpl, IMediaSeeking_vtbl, iface); - - TRACE("(%p/%p)->(%p)\n", iface, This, dRate); - - FIXME("stub\n"); - return E_NOTIMPL; -} - -static HRESULT WINAPI MediaSeekingPassThru_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll) -{ - TRACE("(%p)\n", pPreroll); - - FIXME("stub\n"); - return E_NOTIMPL; -} - -static const IMediaSeekingVtbl IMediaSeekingPassThru_Vtbl = -{ - MediaSeekingPassThru_QueryInterface, - MediaSeekingPassThru_AddRef, - MediaSeekingPassThru_Release, - MediaSeekingPassThru_GetCapabilities, - MediaSeekingPassThru_CheckCapabilities, - MediaSeekingPassThru_IsFormatSupported, - MediaSeekingPassThru_QueryPreferredFormat, - MediaSeekingPassThru_GetTimeFormat, - MediaSeekingPassThru_IsUsingTimeFormat, - MediaSeekingPassThru_SetTimeFormat, - MediaSeekingPassThru_GetDuration, - MediaSeekingPassThru_GetStopPosition, - MediaSeekingPassThru_GetCurrentPosition, - MediaSeekingPassThru_ConvertTimeFormat, - MediaSeekingPassThru_SetPositions, - MediaSeekingPassThru_GetPositions, - MediaSeekingPassThru_GetAvailable, - MediaSeekingPassThru_SetRate, - MediaSeekingPassThru_GetRate, - MediaSeekingPassThru_GetPreroll -}; diff --git a/reactos/dll/directx/quartz/control_private.h b/reactos/dll/directx/quartz/control_private.h deleted file mode 100644 index b5e3997e716..00000000000 --- a/reactos/dll/directx/quartz/control_private.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Filter Seeking and Control Interfaces - * - * Copyright 2003 Robert Shearman - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#ifndef QUARTZ_CONTROL_H -#define QUARTZ_CONTROL_H - -typedef HRESULT (* CHANGEPROC)(IBaseFilter *pUserData); - -typedef struct MediaSeekingImpl -{ - const IMediaSeekingVtbl * lpVtbl; - - ULONG refCount; - IBaseFilter *pUserData; - CHANGEPROC fnChangeStop; - CHANGEPROC fnChangeCurrent; - CHANGEPROC fnChangeRate; - DWORD dwCapabilities; - double dRate; - LONGLONG llCurrent, llStop, llDuration; - GUID timeformat; - PCRITICAL_SECTION crst; -} MediaSeekingImpl; - -HRESULT MediaSeekingImpl_Init(IBaseFilter *pUserData, CHANGEPROC fnChangeStop, CHANGEPROC fnChangeCurrent, CHANGEPROC fnChangeRate, MediaSeekingImpl * pSeeking, PCRITICAL_SECTION crit_sect); - -HRESULT WINAPI MediaSeekingImpl_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities); -HRESULT WINAPI MediaSeekingImpl_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities); -HRESULT WINAPI MediaSeekingImpl_IsFormatSupported(IMediaSeeking * iface, const GUID * pFormat); -HRESULT WINAPI MediaSeekingImpl_QueryPreferredFormat(IMediaSeeking * iface, GUID * pFormat); -HRESULT WINAPI MediaSeekingImpl_GetTimeFormat(IMediaSeeking * iface, GUID * pFormat); -HRESULT WINAPI MediaSeekingImpl_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat); -HRESULT WINAPI MediaSeekingImpl_SetTimeFormat(IMediaSeeking * iface, const GUID * pFormat); -HRESULT WINAPI MediaSeekingImpl_GetDuration(IMediaSeeking * iface, LONGLONG * pDuration); -HRESULT WINAPI MediaSeekingImpl_GetStopPosition(IMediaSeeking * iface, LONGLONG * pStop); -HRESULT WINAPI MediaSeekingImpl_GetCurrentPosition(IMediaSeeking * iface, LONGLONG * pCurrent); -HRESULT WINAPI MediaSeekingImpl_ConvertTimeFormat(IMediaSeeking * iface, LONGLONG * pTarget, const GUID * pTargetFormat, LONGLONG Source, const GUID * pSourceFormat); -HRESULT WINAPI MediaSeekingImpl_SetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, DWORD dwCurrentFlags, LONGLONG * pStop, DWORD dwStopFlags); -HRESULT WINAPI MediaSeekingImpl_GetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, LONGLONG * pStop); -HRESULT WINAPI MediaSeekingImpl_GetAvailable(IMediaSeeking * iface, LONGLONG * pEarliest, LONGLONG * pLatest); -HRESULT WINAPI MediaSeekingImpl_SetRate(IMediaSeeking * iface, double dRate); -HRESULT WINAPI MediaSeekingImpl_GetRate(IMediaSeeking * iface, double * dRate); -HRESULT WINAPI MediaSeekingImpl_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll); - -#endif /*QUARTZ_CONTROL_H*/ diff --git a/reactos/include/dxsdk/strmif.idl b/reactos/dll/directx/quartz/control_tlb.idl similarity index 77% rename from reactos/include/dxsdk/strmif.idl rename to reactos/dll/directx/quartz/control_tlb.idl index a1cad6ba00e..6d1855252a7 100644 --- a/reactos/include/dxsdk/strmif.idl +++ b/reactos/dll/directx/quartz/control_tlb.idl @@ -1,6 +1,4 @@ /* - * Copyright (C) 2002 Robert Shearman - * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -16,15 +14,4 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -import "objidl.idl"; - -#include - -#include - -#include - -#include - -/* TODO: #include */ -#include +#include "control.idl" diff --git a/reactos/dll/directx/quartz/control_tlb.rgs b/reactos/dll/directx/quartz/control_tlb.rgs new file mode 100644 index 00000000000..25e21d609e0 --- /dev/null +++ b/reactos/dll/directx/quartz/control_tlb.rgs @@ -0,0 +1,20 @@ +HKCR +{ + NoRemove Typelib + { + NoRemove '{56A868B0-0AD4-11CE-B03A-0020AF0BA770}' + { + '1.0' = s 'QuartzTypeLib' + { + '0' { win32 = s '%MODULE%' } + FLAGS = s '0' + } + } + } + NoRemove Interface + { + } + NoRemove CLSID + { + } +} diff --git a/reactos/dll/directx/quartz/dsoundrender.c b/reactos/dll/directx/quartz/dsoundrender.c index ddeb3b17e1e..9c4c38b12a9 100644 --- a/reactos/dll/directx/quartz/dsoundrender.c +++ b/reactos/dll/directx/quartz/dsoundrender.c @@ -21,7 +21,6 @@ #include #include "quartz_private.h" -#include "control_private.h" #include "pin.h" //#include "uuids.h" @@ -39,233 +38,299 @@ WINE_DEFAULT_DEBUG_CHANNEL(quartz); -static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0}; +/* NOTE: buffer can still be filled completely, + * but we start waiting until only this amount is buffered + */ +static const REFERENCE_TIME DSoundRenderer_Max_Fill = 150 * 10000; static const IBaseFilterVtbl DSoundRender_Vtbl; -static const IPinVtbl DSoundRender_InputPin_Vtbl; static const IBasicAudioVtbl IBasicAudio_Vtbl; static const IReferenceClockVtbl IReferenceClock_Vtbl; static const IMediaSeekingVtbl IMediaSeeking_Vtbl; static const IAMDirectSoundVtbl IAMDirectSound_Vtbl; +static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl; typedef struct DSoundRenderImpl { - const IBaseFilterVtbl * lpVtbl; - const IBasicAudioVtbl *IBasicAudio_vtbl; - const IReferenceClockVtbl *IReferenceClock_vtbl; - const IAMDirectSoundVtbl *IAMDirectSound_vtbl; + BaseRenderer renderer; + BasicAudio basicAudio; - LONG refCount; - CRITICAL_SECTION csFilter; - FILTER_STATE state; - REFERENCE_TIME rtStreamStart, rtLastStop; - IReferenceClock * pClock; - FILTER_INFO filterInfo; - - InputPin * pInputPin; + IReferenceClock IReferenceClock_iface; + IAMDirectSound IAMDirectSound_iface; + IAMFilterMiscFlags IAMFilterMiscFlags_iface; IDirectSound8 *dsound; LPDIRECTSOUNDBUFFER dsbuffer; DWORD buf_size; - DWORD write_pos; - DWORD write_loops; - - DWORD last_play_pos; - DWORD play_loops; + DWORD in_loop; + DWORD last_playpos, writepos; REFERENCE_TIME play_time; - MediaSeekingImpl mediaSeeking; - HANDLE state_change, blocked; + HANDLE blocked; LONG volume; LONG pan; + + DWORD threadid; + HANDLE advisethread, thread_wait; } DSoundRenderImpl; -/* Seeking is not needed for a renderer, rely on newsegment for the appropriate changes */ -static HRESULT sound_mod_stop(IBaseFilter *iface) +static inline DSoundRenderImpl *impl_from_BaseRenderer(BaseRenderer *iface) { - TRACE("(%p)\n", iface); + return CONTAINING_RECORD(iface, DSoundRenderImpl, renderer); +} + +static inline DSoundRenderImpl *impl_from_IBaseFilter(IBaseFilter *iface) +{ + return CONTAINING_RECORD(iface, DSoundRenderImpl, renderer.filter.IBaseFilter_iface); +} + +static inline DSoundRenderImpl *impl_from_IBasicAudio(IBasicAudio *iface) +{ + return CONTAINING_RECORD(iface, DSoundRenderImpl, basicAudio.IBasicAudio_iface); +} + +static inline DSoundRenderImpl *impl_from_IReferenceClock(IReferenceClock *iface) +{ + return CONTAINING_RECORD(iface, DSoundRenderImpl, IReferenceClock_iface); +} + +static inline DSoundRenderImpl *impl_from_IAMDirectSound(IAMDirectSound *iface) +{ + return CONTAINING_RECORD(iface, DSoundRenderImpl, IAMDirectSound_iface); +} + +static inline DSoundRenderImpl *impl_from_IAMFilterMiscFlags(IAMFilterMiscFlags *iface) +{ + return CONTAINING_RECORD(iface, DSoundRenderImpl, IAMFilterMiscFlags_iface); +} + +static REFERENCE_TIME time_from_pos(DSoundRenderImpl *This, DWORD pos) { + WAVEFORMATEX *wfx = (WAVEFORMATEX*)This->renderer.pInputPin->pin.mtCurrent.pbFormat; + REFERENCE_TIME ret = 10000000; + ret = ret * pos / wfx->nAvgBytesPerSec; + return ret; +} + +static DWORD pos_from_time(DSoundRenderImpl *This, REFERENCE_TIME time) { + WAVEFORMATEX *wfx = (WAVEFORMATEX*)This->renderer.pInputPin->pin.mtCurrent.pbFormat; + REFERENCE_TIME ret = time; + ret *= wfx->nSamplesPerSec; + ret /= 10000000; + ret *= wfx->nBlockAlign; + return ret; +} + +static void DSoundRender_UpdatePositions(DSoundRenderImpl *This, DWORD *seqwritepos, DWORD *minwritepos) { + WAVEFORMATEX *wfx = (WAVEFORMATEX*)This->renderer.pInputPin->pin.mtCurrent.pbFormat; + BYTE *buf1, *buf2; + DWORD size1, size2, playpos, writepos, old_writepos, old_playpos, adv; + BOOL writepos_set = This->writepos < This->buf_size; + + /* Update position and zero */ + old_writepos = This->writepos; + old_playpos = This->last_playpos; + if (old_writepos <= old_playpos) + old_writepos += This->buf_size; + + IDirectSoundBuffer_GetCurrentPosition(This->dsbuffer, &playpos, &writepos); + if (old_playpos > playpos) { + adv = This->buf_size + playpos - old_playpos; + This->play_time += time_from_pos(This, This->buf_size); + } else + adv = playpos - old_playpos; + This->last_playpos = playpos; + if (adv) { + TRACE("Moving from %u to %u: clearing %u bytes\n", old_playpos, playpos, adv); + IDirectSoundBuffer_Lock(This->dsbuffer, old_playpos, adv, (void**)&buf1, &size1, (void**)&buf2, &size2, 0); + memset(buf1, wfx->wBitsPerSample == 8 ? 128 : 0, size1); + memset(buf2, wfx->wBitsPerSample == 8 ? 128 : 0, size2); + IDirectSoundBuffer_Unlock(This->dsbuffer, buf1, size1, buf2, size2); + } + *minwritepos = writepos; + if (!writepos_set || old_writepos < writepos) { + if (writepos_set) { + This->writepos = This->buf_size; + FIXME("Underrun of data occurred!\n"); + } + *seqwritepos = writepos; + } else + *seqwritepos = This->writepos; +} + +static HRESULT DSoundRender_GetWritePos(DSoundRenderImpl *This, DWORD *ret_writepos, REFERENCE_TIME write_at, DWORD *pfree, DWORD *skip) +{ + WAVEFORMATEX *wfx = (WAVEFORMATEX*)This->renderer.pInputPin->pin.mtCurrent.pbFormat; + DWORD writepos, min_writepos, playpos; + REFERENCE_TIME max_lag = 50 * 10000; + REFERENCE_TIME min_lag = 25 * 10000; + REFERENCE_TIME cur, writepos_t, delta_t; + + DSoundRender_UpdatePositions(This, &writepos, &min_writepos); + playpos = This->last_playpos; + if (This->renderer.filter.pClock == &This->IReferenceClock_iface) { + max_lag = min_lag; + cur = This->play_time + time_from_pos(This, playpos); + cur -= This->renderer.filter.rtStreamStart; + } else if (This->renderer.filter.pClock) { + IReferenceClock_GetTime(This->renderer.filter.pClock, &cur); + cur -= This->renderer.filter.rtStreamStart; + } else + write_at = -1; + + if (writepos == min_writepos) + max_lag = 0; + + *skip = 0; + if (write_at < 0) { + *ret_writepos = writepos; + goto end; + } + + if (writepos >= playpos) + writepos_t = cur + time_from_pos(This, writepos - playpos); + else + writepos_t = cur + time_from_pos(This, This->buf_size + writepos - playpos); + + /* write_at: Starting time of sample */ + /* cur: current time of play position */ + /* writepos_t: current time of our pointer play position */ + delta_t = write_at - writepos_t; + if (delta_t >= -max_lag && delta_t <= max_lag) { + TRACE("Continuing from old position\n"); + *ret_writepos = writepos; + } else if (delta_t < 0) { + REFERENCE_TIME past, min_writepos_t; + WARN("Delta too big %i/%i, overwriting old data or even skipping\n", (int)delta_t / 10000, (int)max_lag / 10000); + if (min_writepos >= playpos) + min_writepos_t = cur + time_from_pos(This, min_writepos - playpos); + else + min_writepos_t = cur + time_from_pos(This, This->buf_size - playpos + min_writepos); + past = min_writepos_t - write_at; + if (past >= 0) { + DWORD skipbytes = pos_from_time(This, past); + WARN("Skipping %u bytes\n", skipbytes); + *skip = skipbytes; + *ret_writepos = min_writepos; + } else { + DWORD aheadbytes = pos_from_time(This, -past); + WARN("Advancing %u bytes\n", aheadbytes); + *ret_writepos = (min_writepos + aheadbytes) % This->buf_size; + } + } else /* delta_t > 0 */ { + DWORD aheadbytes; + WARN("Delta too big %i/%i, too far ahead\n", (int)delta_t / 10000, (int)max_lag / 10000); + aheadbytes = pos_from_time(This, delta_t); + WARN("Advancing %u bytes\n", aheadbytes); + if (delta_t >= DSoundRenderer_Max_Fill) + return S_FALSE; + *ret_writepos = (min_writepos + aheadbytes) % This->buf_size; + } +end: + if (playpos > *ret_writepos) + *pfree = playpos - *ret_writepos; + else if (playpos == *ret_writepos) + *pfree = This->buf_size - wfx->nBlockAlign; + else + *pfree = This->buf_size + playpos - *ret_writepos; + if (time_from_pos(This, This->buf_size - *pfree) >= DSoundRenderer_Max_Fill) { + TRACE("Blocked: too full %i / %i\n", (int)(time_from_pos(This, This->buf_size - *pfree)/10000), (int)(DSoundRenderer_Max_Fill / 10000)); + return S_FALSE; + } return S_OK; } -static HRESULT sound_mod_start(IBaseFilter *iface) +static HRESULT DSoundRender_HandleEndOfStream(DSoundRenderImpl *This) { - TRACE("(%p)\n", iface); + while (1) + { + DWORD pos1, pos2; + DSoundRender_UpdatePositions(This, &pos1, &pos2); + if (pos1 == pos2) + break; + + This->in_loop = 1; + LeaveCriticalSection(&This->renderer.filter.csFilter); + LeaveCriticalSection(&This->renderer.csRenderLock); + WaitForSingleObject(This->blocked, 10); + EnterCriticalSection(&This->renderer.filter.csFilter); + EnterCriticalSection(&This->renderer.csRenderLock); + This->in_loop = 0; + } return S_OK; } -static HRESULT sound_mod_rate(IBaseFilter *iface) -{ - DSoundRenderImpl *This = (DSoundRenderImpl *)iface; - - WAVEFORMATEX *format = (WAVEFORMATEX*)This->pInputPin->pin.mtCurrent.pbFormat; - DWORD freq = format->nSamplesPerSec; - double rate = This->mediaSeeking.dRate; - - freq = (DWORD)((double)freq * rate); - - TRACE("(%p)\n", iface); - - if (freq > DSBFREQUENCY_MAX) - return VFW_E_UNSUPPORTED_AUDIO; - - if (freq < DSBFREQUENCY_MIN) - return VFW_E_UNSUPPORTED_AUDIO; - - return S_OK; -} - -static inline HRESULT DSoundRender_GetPos(DSoundRenderImpl *This, DWORD *pPlayPos, REFERENCE_TIME *pRefTime) +static HRESULT DSoundRender_SendSampleData(DSoundRenderImpl* This, REFERENCE_TIME tStart, REFERENCE_TIME tStop, const BYTE *data, DWORD size) { HRESULT hr; - EnterCriticalSection(&This->csFilter); - { - DWORD state; - DWORD write_pos; + while (size && This->renderer.filter.state != State_Stopped) { + DWORD writepos, skip = 0, free, size1, size2, ret; + BYTE *buf1, *buf2; - hr = IDirectSoundBuffer_GetStatus(This->dsbuffer, &state); - if (SUCCEEDED(hr) && !(state & DSBSTATUS_PLAYING) && This->state == State_Running) - { - TRACE("Not playing, kickstarting the engine\n"); - - hr = IDirectSoundBuffer_Play(This->dsbuffer, 0, 0, DSBPLAY_LOOPING); - if (FAILED(hr)) - ERR("Can't play sound buffer (%x)\n", hr); - } - - if (SUCCEEDED(hr)) - hr = IDirectSoundBuffer_GetCurrentPosition(This->dsbuffer, pPlayPos, &write_pos); - if (hr == S_OK) - { - DWORD play_pos = *pPlayPos; - - if (play_pos < This->last_play_pos) - This->play_loops++; - This->last_play_pos = play_pos; - - /* If we really fell behind, start at the next possible position - * Also happens when just starting playback for the first time, - * or when flushing - */ - if ((This->play_loops*This->buf_size)+play_pos >= - (This->write_loops*This->buf_size)+This->write_pos) - This->write_pos = write_pos; - - if (pRefTime) - { - REFERENCE_TIME play_time; - play_time = ((REFERENCE_TIME)This->play_loops*10000000) + - ((REFERENCE_TIME)play_pos*10000000/This->buf_size); - - /* Don't let time run backwards */ - if(play_time-This->play_time > 0) - This->play_time = play_time; - else - hr = S_FALSE; - - *pRefTime = This->play_time; - } - } - } - LeaveCriticalSection(&This->csFilter); - - return hr; -} - -static HRESULT DSoundRender_SendSampleData(DSoundRenderImpl* This, const BYTE *data, DWORD size) -{ - HRESULT hr = S_OK; - LPBYTE lpbuf1 = NULL; - LPBYTE lpbuf2 = NULL; - DWORD dwsize1 = 0; - DWORD dwsize2 = 0; - DWORD size2; - DWORD play_pos,buf_free; - - do { - - hr = DSoundRender_GetPos(This, &play_pos, NULL); - if (hr != DS_OK) - { - ERR("GetPos returned error: %x\n", hr); - break; - } - if (This->write_pos <= play_pos) - buf_free = play_pos-This->write_pos; + if (This->renderer.filter.state == State_Running) + hr = DSoundRender_GetWritePos(This, &writepos, tStart, &free, &skip); else - buf_free = This->buf_size - This->write_pos + play_pos; + hr = S_FALSE; - /* Wait for enough of the buffer to empty before filling it */ - if(buf_free < This->buf_size/4) - { - Sleep(50); + if (hr != S_OK) { + This->in_loop = 1; + LeaveCriticalSection(&This->renderer.csRenderLock); + ret = WaitForSingleObject(This->blocked, 10); + EnterCriticalSection(&This->renderer.csRenderLock); + This->in_loop = 0; + if (This->renderer.pInputPin->flushing || + This->renderer.filter.state == State_Stopped) { + return This->renderer.filter.state == State_Paused ? S_OK : VFW_E_WRONG_STATE; + } + if (ret != WAIT_TIMEOUT) + ERR("%x\n", ret); continue; } + tStart = -1; - size2 = min(buf_free, size); - hr = IDirectSoundBuffer_Lock(This->dsbuffer, This->write_pos, size2, (LPVOID *)&lpbuf1, &dwsize1, (LPVOID *)&lpbuf2, &dwsize2, 0); + if (skip) + FIXME("Sample dropped %u of %u bytes\n", skip, size); + if (skip >= size) + return S_OK; + data += skip; + size -= skip; + + hr = IDirectSoundBuffer_Lock(This->dsbuffer, writepos, min(free, size), (void**)&buf1, &size1, (void**)&buf2, &size2, 0); if (hr != DS_OK) { ERR("Unable to lock sound buffer! (%x)\n", hr); break; } - /* TRACE("write_pos=%d, size=%d, sz1=%d, sz2=%d\n", This->write_pos, size2, dwsize1, dwsize2); */ - - memcpy(lpbuf1, data, dwsize1); - if (dwsize2) - memcpy(lpbuf2, data + dwsize1, dwsize2); - - hr = IDirectSoundBuffer_Unlock(This->dsbuffer, lpbuf1, dwsize1, lpbuf2, dwsize2); - if (hr != DS_OK) - ERR("Unable to unlock sound buffer! (%x)\n", hr); - - size -= dwsize1 + dwsize2; - data += dwsize1 + dwsize2; - This->write_pos += dwsize1 + dwsize2; - if (This->write_pos >= This->buf_size) - { - This->write_pos -= This->buf_size; - This->write_loops++; - } - } while (size && This->state == State_Running); - - return hr; + memcpy(buf1, data, size1); + if (size2) + memcpy(buf2, data+size1, size2); + IDirectSoundBuffer_Unlock(This->dsbuffer, buf1, size1, buf2, size2); + This->writepos = (writepos + size1 + size2) % This->buf_size; + TRACE("Wrote %u bytes at %u, next at %u - (%u/%u)\n", size1+size2, writepos, This->writepos, free, size); + data += size1 + size2; + size -= size1 + size2; + } + return S_OK; } -static HRESULT DSoundRender_Sample(LPVOID iface, IMediaSample * pSample) +static HRESULT WINAPI DSoundRender_ShouldDrawSampleNow(BaseRenderer *This, IMediaSample *pMediaSample, REFERENCE_TIME *pStartTime, REFERENCE_TIME *pEndTime) { - DSoundRenderImpl *This = iface; - LPBYTE pbSrcStream = NULL; - LONG cbSrcStream = 0; - REFERENCE_TIME tStart, tStop; + /* We time ourselves do not use the base renderers timing */ + return S_OK; +} + + +static HRESULT WINAPI DSoundRender_PrepareReceive(BaseRenderer *iface, IMediaSample *pSample) +{ + DSoundRenderImpl *This = impl_from_BaseRenderer(iface); HRESULT hr; AM_MEDIA_TYPE *amt; - TRACE("%p %p\n", iface, pSample); - - /* Slightly incorrect, Pause completes when a frame is received so we should signal - * pause completion here, but for sound playing a single frame doesn't make sense - */ - - EnterCriticalSection(&This->csFilter); - - if (This->pInputPin->end_of_stream || This->pInputPin->flushing) - { - LeaveCriticalSection(&This->csFilter); - return S_FALSE; - } - - if (This->state == State_Stopped) - { - LeaveCriticalSection(&This->csFilter); - return VFW_E_WRONG_STATE; - } - if (IMediaSample_GetMediaType(pSample, &amt) == S_OK) { - AM_MEDIA_TYPE *orig = &This->pInputPin->pin.mtCurrent; + AM_MEDIA_TYPE *orig = &This->renderer.pInputPin->pin.mtCurrent; WAVEFORMATEX *origfmt = (WAVEFORMATEX *)orig->pbFormat; WAVEFORMATEX *newfmt = (WAVEFORMATEX *)amt->pbFormat; @@ -280,91 +345,76 @@ static HRESULT DSoundRender_Sample(LPVOID iface, IMediaSample * pSample) hr = IDirectSoundBuffer_SetFrequency(This->dsbuffer, newfmt->nSamplesPerSec); if (FAILED(hr)) - { - LeaveCriticalSection(&This->csFilter); return VFW_E_TYPE_NOT_ACCEPTED; - } FreeMediaType(orig); CopyMediaType(orig, amt); IMediaSample_SetMediaType(pSample, NULL); } } else - { - LeaveCriticalSection(&This->csFilter); return VFW_E_TYPE_NOT_ACCEPTED; - } } + return S_OK; +} - SetEvent(This->state_change); +static HRESULT WINAPI DSoundRender_DoRenderSample(BaseRenderer *iface, IMediaSample * pSample) +{ + DSoundRenderImpl *This = impl_from_BaseRenderer(iface); + LPBYTE pbSrcStream = NULL; + LONG cbSrcStream = 0; + REFERENCE_TIME tStart, tStop; + HRESULT hr; + + TRACE("%p %p\n", iface, pSample); + + /* Slightly incorrect, Pause completes when a frame is received so we should signal + * pause completion here, but for sound playing a single frame doesn't make sense + */ hr = IMediaSample_GetPointer(pSample, &pbSrcStream); if (FAILED(hr)) { ERR("Cannot get pointer to sample data (%x)\n", hr); - LeaveCriticalSection(&This->csFilter); return hr; } hr = IMediaSample_GetTime(pSample, &tStart, &tStop); - if (FAILED(hr)) + if (FAILED(hr)) { ERR("Cannot get sample time (%x)\n", hr); + tStart = tStop = -1; + } - if (This->rtLastStop != tStart && (IMediaSample_IsDiscontinuity(pSample) == S_FALSE)) - WARN("Unexpected discontinuity: Last: %u.%03u, tStart: %u.%03u\n", - (DWORD)(This->rtLastStop / 10000000), (DWORD)((This->rtLastStop / 10000)%1000), - (DWORD)(tStart / 10000000), (DWORD)((tStart / 10000)%1000)); - This->rtLastStop = tStop; + IMediaSample_IsDiscontinuity(pSample); if (IMediaSample_IsPreroll(pSample) == S_OK) { TRACE("Preroll!\n"); - LeaveCriticalSection(&This->csFilter); return S_OK; } - if (This->state == State_Paused) - { - LeaveCriticalSection(&This->csFilter); - WaitForSingleObject(This->blocked, INFINITE); - EnterCriticalSection(&This->csFilter); - if (This->state == State_Stopped) - { - LeaveCriticalSection(&This->csFilter); - return VFW_E_WRONG_STATE; - } - - if (This->state == State_Paused) - { - /* Assuming we return because of flushing */ - TRACE("Flushing\n"); - LeaveCriticalSection(&This->csFilter); - return S_OK; - } - } - cbSrcStream = IMediaSample_GetActualDataLength(pSample); TRACE("Sample data ptr = %p, size = %d\n", pbSrcStream, cbSrcStream); -#if 0 /* For debugging purpose */ - { - int i; - for(i = 0; i < cbSrcStream; i++) - { - if ((i!=0) && !(i%16)) - TRACE("\n"); - TRACE("%02x ", pbSrcStream[i]); - } - TRACE("\n"); + hr = DSoundRender_SendSampleData(This, tStart, tStop, pbSrcStream, cbSrcStream); + if (This->renderer.filter.state == State_Running && This->renderer.filter.pClock && tStart >= 0) { + REFERENCE_TIME jitter, now = 0; + Quality q; + IReferenceClock_GetTime(This->renderer.filter.pClock, &now); + jitter = now - This->renderer.filter.rtStreamStart - tStart; + if (jitter <= -DSoundRenderer_Max_Fill) + jitter += DSoundRenderer_Max_Fill; + else if (jitter < 0) + jitter = 0; + q.Type = (jitter > 0 ? Famine : Flood); + q.Proportion = 1.; + q.Late = jitter; + q.TimeStamp = tStart; + IQualityControl_Notify((IQualityControl *)This->renderer.qcimpl, (IBaseFilter*)This, q); } -#endif - - hr = DSoundRender_SendSampleData(This, pbSrcStream, cbSrcStream); - LeaveCriticalSection(&This->csFilter); return hr; } -static HRESULT DSoundRender_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt) +static HRESULT WINAPI DSoundRender_CheckMediaType(BaseRenderer *iface, const AM_MEDIA_TYPE * pmt) { WAVEFORMATEX* format; @@ -386,10 +436,189 @@ static HRESULT DSoundRender_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt) return S_OK; } +static VOID WINAPI DSoundRender_OnStopStreaming(BaseRenderer * iface) +{ + DSoundRenderImpl *This = impl_from_BaseRenderer(iface); + + TRACE("(%p/%p)->()\n", This, iface); + + IDirectSoundBuffer_Stop(This->dsbuffer); + This->writepos = This->buf_size; + SetEvent(This->blocked); +} + +static VOID WINAPI DSoundRender_OnStartStreaming(BaseRenderer * iface) +{ + DSoundRenderImpl *This = impl_from_BaseRenderer(iface); + + TRACE("(%p)\n", This); + + if (This->renderer.pInputPin->pin.pConnectedTo) + { + if (This->renderer.filter.state == State_Paused) + { + /* Unblock our thread, state changing from paused to running doesn't need a reset for state change */ + SetEvent(This->blocked); + } + IDirectSoundBuffer_Play(This->dsbuffer, 0, 0, DSBPLAY_LOOPING); + ResetEvent(This->blocked); + } +} + +static HRESULT WINAPI DSoundRender_CompleteConnect(BaseRenderer * iface, IPin * pReceivePin) +{ + DSoundRenderImpl *This = impl_from_BaseRenderer(iface); + const AM_MEDIA_TYPE * pmt = &This->renderer.pInputPin->pin.mtCurrent; + HRESULT hr = S_OK; + WAVEFORMATEX *format; + DSBUFFERDESC buf_desc; + + TRACE("(%p)->(%p)\n", This, pReceivePin); + dump_AM_MEDIA_TYPE(pmt); + + 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; + + This->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_GLOBALFOCUS | + DSBCAPS_GETCURRENTPOSITION2; + buf_desc.dwBufferBytes = This->buf_size; + buf_desc.lpwfxFormat = format; + hr = IDirectSound_CreateSoundBuffer(This->dsound, &buf_desc, &This->dsbuffer, NULL); + This->writepos = This->buf_size; + if (FAILED(hr)) + ERR("Can't create sound buffer (%x)\n", hr); + + if (SUCCEEDED(hr)) + { + hr = IDirectSoundBuffer_SetVolume(This->dsbuffer, This->volume); + if (FAILED(hr)) + ERR("Can't set volume to %d (%x)\n", This->volume, hr); + + hr = IDirectSoundBuffer_SetPan(This->dsbuffer, This->pan); + if (FAILED(hr)) + ERR("Can't set pan to %d (%x)\n", This->pan, hr); + hr = S_OK; + } + + if (FAILED(hr) && hr != VFW_E_ALREADY_CONNECTED) + { + if (This->dsbuffer) + IDirectSoundBuffer_Release(This->dsbuffer); + This->dsbuffer = NULL; + } + + return hr; +} + +static HRESULT WINAPI DSoundRender_BreakConnect(BaseRenderer* iface) +{ + DSoundRenderImpl *This = impl_from_BaseRenderer(iface); + + TRACE("(%p)->()\n", iface); + + if (This->threadid) { + PostThreadMessageW(This->threadid, WM_APP, 0, 0); + LeaveCriticalSection(This->renderer.pInputPin->pin.pCritSec); + WaitForSingleObject(This->advisethread, INFINITE); + EnterCriticalSection(This->renderer.pInputPin->pin.pCritSec); + CloseHandle(This->advisethread); + } + if (This->dsbuffer) + IDirectSoundBuffer_Release(This->dsbuffer); + This->dsbuffer = NULL; + + return S_OK; +} + +static HRESULT WINAPI DSoundRender_EndOfStream(BaseRenderer* iface) +{ + DSoundRenderImpl *This = impl_from_BaseRenderer(iface); + HRESULT hr; + + TRACE("(%p)->()\n",iface); + + hr = BaseRendererImpl_EndOfStream(iface); + if (hr != S_OK) + { + ERR("%08x\n", hr); + return hr; + } + + hr = DSoundRender_HandleEndOfStream(This); + + return hr; +} + +static HRESULT WINAPI DSoundRender_BeginFlush(BaseRenderer* iface) +{ + DSoundRenderImpl *This = impl_from_BaseRenderer(iface); + + TRACE("\n"); + BaseRendererImpl_BeginFlush(iface); + SetEvent(This->blocked); + + return S_OK; +} + +static HRESULT WINAPI DSoundRender_EndFlush(BaseRenderer* iface) +{ + DSoundRenderImpl *This = impl_from_BaseRenderer(iface); + + TRACE("\n"); + + BaseRendererImpl_EndFlush(iface); + if (This->renderer.filter.state != State_Stopped) + ResetEvent(This->blocked); + + if (This->dsbuffer) + { + LPBYTE buffer; + DWORD size; + + /* Force a reset */ + IDirectSoundBuffer_Lock(This->dsbuffer, 0, 0, (LPVOID *)&buffer, &size, NULL, NULL, DSBLOCK_ENTIREBUFFER); + memset(buffer, 0, size); + IDirectSoundBuffer_Unlock(This->dsbuffer, buffer, size, NULL, 0); + This->writepos = This->buf_size; + } + + return S_OK; +} + +static const BaseRendererFuncTable BaseFuncTable = { + DSoundRender_CheckMediaType, + DSoundRender_DoRenderSample, + /**/ + NULL, + NULL, + NULL, + DSoundRender_OnStartStreaming, + DSoundRender_OnStopStreaming, + NULL, + NULL, + NULL, + DSoundRender_ShouldDrawSampleNow, + DSoundRender_PrepareReceive, + /**/ + DSoundRender_CompleteConnect, + DSoundRender_BreakConnect, + DSoundRender_EndOfStream, + DSoundRender_BeginFlush, + DSoundRender_EndFlush, +}; + HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv) { HRESULT hr; - PIN_INFO piInput; DSoundRenderImpl * pDSoundRender; TRACE("(%p, %p)\n", pUnkOuter, ppv); @@ -398,26 +627,18 @@ HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv) if (pUnkOuter) return CLASS_E_NOAGGREGATION; - + pDSoundRender = CoTaskMemAlloc(sizeof(DSoundRenderImpl)); if (!pDSoundRender) return E_OUTOFMEMORY; ZeroMemory(pDSoundRender, sizeof(DSoundRenderImpl)); - pDSoundRender->lpVtbl = &DSoundRender_Vtbl; - pDSoundRender->IBasicAudio_vtbl = &IBasicAudio_Vtbl; - pDSoundRender->IReferenceClock_vtbl = &IReferenceClock_Vtbl; - pDSoundRender->IAMDirectSound_vtbl = &IAMDirectSound_Vtbl; - pDSoundRender->refCount = 1; - InitializeCriticalSection(&pDSoundRender->csFilter); - pDSoundRender->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DSoundRenderImpl.csFilter"); - pDSoundRender->state = State_Stopped; + hr = BaseRenderer_Init(&pDSoundRender->renderer, &DSoundRender_Vtbl, (IUnknown*)pDSoundRender, &CLSID_DSoundRender, (DWORD_PTR)(__FILE__ ": DSoundRenderImpl.csFilter"), &BaseFuncTable); - /* construct input pin */ - piInput.dir = PINDIR_INPUT; - piInput.pFilter = (IBaseFilter *)pDSoundRender; - lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0])); - hr = InputPin_Construct(&DSoundRender_InputPin_Vtbl, &piInput, DSoundRender_Sample, pDSoundRender, DSoundRender_QueryAccept, NULL, &pDSoundRender->csFilter, NULL, (IPin **)&pDSoundRender->pInputPin); + BasicAudio_Init(&pDSoundRender->basicAudio,&IBasicAudio_Vtbl); + pDSoundRender->IReferenceClock_iface.lpVtbl = &IReferenceClock_Vtbl; + pDSoundRender->IAMDirectSound_iface.lpVtbl = &IAMDirectSound_Vtbl; + pDSoundRender->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_Vtbl; if (SUCCEEDED(hr)) { @@ -425,18 +646,27 @@ HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv) if (FAILED(hr)) ERR("Cannot create Direct Sound object (%x)\n", hr); else - IDirectSound_SetCooperativeLevel(pDSoundRender->dsound, GetDesktopWindow(), DSSCL_PRIORITY); + hr = IDirectSound_SetCooperativeLevel(pDSoundRender->dsound, GetDesktopWindow(), DSSCL_PRIORITY); + if (SUCCEEDED(hr)) { + IDirectSoundBuffer *buf; + DSBUFFERDESC buf_desc; + memset(&buf_desc,0,sizeof(DSBUFFERDESC)); + buf_desc.dwSize = sizeof(DSBUFFERDESC); + buf_desc.dwFlags = DSBCAPS_PRIMARYBUFFER; + hr = IDirectSound_CreateSoundBuffer(pDSoundRender->dsound, &buf_desc, &buf, NULL); + if (SUCCEEDED(hr)) { + IDirectSoundBuffer_Play(buf, 0, 0, DSBPLAY_LOOPING); + IDirectSoundBuffer_Release(buf); + } + hr = S_OK; + } } if (SUCCEEDED(hr)) { - MediaSeekingImpl_Init((IBaseFilter*)pDSoundRender, sound_mod_stop, sound_mod_start, sound_mod_rate, &pDSoundRender->mediaSeeking, &pDSoundRender->csFilter); - pDSoundRender->mediaSeeking.lpVtbl = &IMediaSeeking_Vtbl; + pDSoundRender->blocked = CreateEventW(NULL, TRUE, TRUE, NULL); - pDSoundRender->state_change = CreateEventW(NULL, TRUE, TRUE, NULL); - pDSoundRender->blocked = CreateEventW(NULL, FALSE, FALSE, NULL); - - if (!pDSoundRender->state_change || !pDSoundRender->blocked) + if (!pDSoundRender->blocked || FAILED(hr)) { IUnknown_Release((IUnknown *)pDSoundRender); return HRESULT_FROM_WIN32(GetLastError()); @@ -446,10 +676,7 @@ HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv) } else { - if (pDSoundRender->pInputPin) - IPin_Release((IPin*)pDSoundRender->pInputPin); - pDSoundRender->csFilter.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&pDSoundRender->csFilter); + BaseRendererImpl_Release(&pDSoundRender->renderer.filter.IBaseFilter_iface); CoTaskMemFree(pDSoundRender); } @@ -458,27 +685,26 @@ HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv) static HRESULT WINAPI DSoundRender_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv) { - DSoundRenderImpl *This = (DSoundRenderImpl *)iface; + DSoundRenderImpl *This = impl_from_IBaseFilter(iface); TRACE("(%p, %p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv); *ppv = NULL; - if (IsEqualIID(riid, &IID_IUnknown)) - *ppv = This; - else if (IsEqualIID(riid, &IID_IPersist)) - *ppv = This; - else if (IsEqualIID(riid, &IID_IMediaFilter)) - *ppv = This; - else if (IsEqualIID(riid, &IID_IBaseFilter)) - *ppv = This; - else if (IsEqualIID(riid, &IID_IBasicAudio)) - *ppv = &This->IBasicAudio_vtbl; + if (IsEqualIID(riid, &IID_IBasicAudio)) + *ppv = &This->basicAudio.IBasicAudio_iface; else if (IsEqualIID(riid, &IID_IReferenceClock)) - *ppv = &This->IReferenceClock_vtbl; - else if (IsEqualIID(riid, &IID_IMediaSeeking)) - *ppv = &This->mediaSeeking.lpVtbl; + *ppv = &This->IReferenceClock_iface; else if (IsEqualIID(riid, &IID_IAMDirectSound)) - *ppv = &This->IAMDirectSound_vtbl; + *ppv = &This->IAMDirectSound_iface; + else if (IsEqualIID(riid, &IID_IAMFilterMiscFlags)) + *ppv = &This->IAMFilterMiscFlags_iface; + else + { + HRESULT hr; + hr = BaseRendererImpl_QueryInterface(iface, riid, ppv); + if (SUCCEEDED(hr)) + return hr; + } if (*ppv) { @@ -492,29 +718,20 @@ static HRESULT WINAPI DSoundRender_QueryInterface(IBaseFilter * iface, REFIID ri return E_NOINTERFACE; } -static ULONG WINAPI DSoundRender_AddRef(IBaseFilter * iface) -{ - DSoundRenderImpl *This = (DSoundRenderImpl *)iface; - ULONG refCount = InterlockedIncrement(&This->refCount); - - TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1); - - return refCount; -} - static ULONG WINAPI DSoundRender_Release(IBaseFilter * iface) { - DSoundRenderImpl *This = (DSoundRenderImpl *)iface; - ULONG refCount = InterlockedDecrement(&This->refCount); + DSoundRenderImpl *This = impl_from_IBaseFilter(iface); + ULONG refCount = BaseRendererImpl_Release(iface); TRACE("(%p)->() Release from %d\n", This, refCount + 1); if (!refCount) { - IPin *pConnectedTo; - - if (This->pClock) - IReferenceClock_Release(This->pClock); + if (This->threadid) { + PostThreadMessageW(This->threadid, WM_APP, 0, 0); + WaitForSingleObject(This->advisethread, INFINITE); + CloseHandle(This->advisethread); + } if (This->dsbuffer) IDirectSoundBuffer_Release(This->dsbuffer); @@ -522,599 +739,99 @@ static ULONG WINAPI DSoundRender_Release(IBaseFilter * iface) if (This->dsound) IDirectSound_Release(This->dsound); This->dsound = NULL; - - if (SUCCEEDED(IPin_ConnectedTo((IPin *)This->pInputPin, &pConnectedTo))) - { - IPin_Disconnect(pConnectedTo); - IPin_Release(pConnectedTo); - } - IPin_Disconnect((IPin *)This->pInputPin); - IPin_Release((IPin *)This->pInputPin); - - This->lpVtbl = NULL; - This->IBasicAudio_vtbl = NULL; - - This->csFilter.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&This->csFilter); - - CloseHandle(This->state_change); + BasicAudio_Destroy(&This->basicAudio); CloseHandle(This->blocked); TRACE("Destroying Audio Renderer\n"); CoTaskMemFree(This); - + return 0; } else return refCount; } -/** IPersist methods **/ - -static HRESULT WINAPI DSoundRender_GetClassID(IBaseFilter * iface, CLSID * pClsid) -{ - DSoundRenderImpl *This = (DSoundRenderImpl *)iface; - TRACE("(%p/%p)->(%p)\n", This, iface, pClsid); - - *pClsid = CLSID_DSoundRender; - - return S_OK; -} - -/** IMediaFilter methods **/ - -static HRESULT WINAPI DSoundRender_Stop(IBaseFilter * iface) -{ - HRESULT hr = S_OK; - DSoundRenderImpl *This = (DSoundRenderImpl *)iface; - - TRACE("(%p/%p)->()\n", This, iface); - - EnterCriticalSection(&This->csFilter); - { - DWORD state = 0; - if (This->dsbuffer) - { - hr = IDirectSoundBuffer_GetStatus(This->dsbuffer, &state); - if (SUCCEEDED(hr)) - { - if (state & DSBSTATUS_PLAYING) - hr = IDirectSoundBuffer_Stop(This->dsbuffer); - } - } - if (SUCCEEDED(hr)) - This->state = State_Stopped; - - /* Complete our transition */ - SetEvent(This->state_change); - SetEvent(This->blocked); - } - LeaveCriticalSection(&This->csFilter); - - return hr; -} - static HRESULT WINAPI DSoundRender_Pause(IBaseFilter * iface) { HRESULT hr = S_OK; DSoundRenderImpl *This = (DSoundRenderImpl *)iface; - + TRACE("(%p/%p)->()\n", This, iface); - EnterCriticalSection(&This->csFilter); - if (This->state != State_Paused) + EnterCriticalSection(&This->renderer.csRenderLock); + if (This->renderer.filter.state != State_Paused) { - DWORD state = 0; - if (This->state == State_Stopped) + if (This->renderer.filter.state == State_Stopped) { - This->pInputPin->end_of_stream = 0; + if (This->renderer.pInputPin->pin.pConnectedTo) + ResetEvent(This->renderer.evComplete); + This->renderer.pInputPin->end_of_stream = 0; } - if (This->dsbuffer) - { - hr = IDirectSoundBuffer_GetStatus(This->dsbuffer, &state); - if (SUCCEEDED(hr)) - { - if (state & DSBSTATUS_PLAYING) - hr = IDirectSoundBuffer_Stop(This->dsbuffer); - } - } + hr = IDirectSoundBuffer_Stop(This->dsbuffer); if (SUCCEEDED(hr)) - This->state = State_Paused; + This->renderer.filter.state = State_Paused; ResetEvent(This->blocked); - ResetEvent(This->state_change); + ResetEvent(This->renderer.RenderEvent); } - LeaveCriticalSection(&This->csFilter); + ResetEvent(This->renderer.ThreadSignal); + LeaveCriticalSection(&This->renderer.csRenderLock); return hr; } -static HRESULT WINAPI DSoundRender_Run(IBaseFilter * iface, REFERENCE_TIME tStart) -{ - HRESULT hr = S_OK; - DSoundRenderImpl *This = (DSoundRenderImpl *)iface; - - TRACE("(%p/%p)->(%s)\n", This, iface, wine_dbgstr_longlong(tStart)); - - EnterCriticalSection(&This->csFilter); - { - This->rtStreamStart = tStart; - if (This->state == State_Paused) - { - /* Unblock our thread, state changing from paused to running doesn't need a reset for state change */ - SetEvent(This->blocked); - } - else if (This->state == State_Stopped) - { - ResetEvent(This->state_change); - This->pInputPin->end_of_stream = 0; - } - - This->state = State_Running; - } - LeaveCriticalSection(&This->csFilter); - - return hr; -} - -static HRESULT WINAPI DSoundRender_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState) -{ - HRESULT hr; - DSoundRenderImpl *This = (DSoundRenderImpl *)iface; - - TRACE("(%p/%p)->(%d, %p)\n", This, iface, dwMilliSecsTimeout, pState); - - if (WaitForSingleObject(This->state_change, dwMilliSecsTimeout) == WAIT_TIMEOUT) - hr = VFW_S_STATE_INTERMEDIATE; - else - hr = S_OK; - - EnterCriticalSection(&This->csFilter); - { - *pState = This->state; - } - LeaveCriticalSection(&This->csFilter); - - return hr; -} - -static HRESULT WINAPI DSoundRender_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock) -{ - DSoundRenderImpl *This = (DSoundRenderImpl *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, pClock); - - EnterCriticalSection(&This->csFilter); - { - if (This->pClock) - IReferenceClock_Release(This->pClock); - This->pClock = pClock; - if (This->pClock) - IReferenceClock_AddRef(This->pClock); - } - LeaveCriticalSection(&This->csFilter); - - return S_OK; -} - -static HRESULT WINAPI DSoundRender_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock) -{ - DSoundRenderImpl *This = (DSoundRenderImpl *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, ppClock); - - EnterCriticalSection(&This->csFilter); - { - *ppClock = This->pClock; - if (This->pClock) - IReferenceClock_AddRef(This->pClock); - } - LeaveCriticalSection(&This->csFilter); - - return S_OK; -} - -/** IBaseFilter implementation **/ - -static HRESULT DSoundRender_GetPin(IBaseFilter *iface, ULONG pos, IPin **pin, DWORD *lastsynctick) -{ - DSoundRenderImpl *This = (DSoundRenderImpl *)iface; - - /* Our pins are static, not changing so setting static tick count is ok */ - *lastsynctick = 0; - - if (pos >= 1) - return S_FALSE; - - *pin = (IPin *)This->pInputPin; - IPin_AddRef(*pin); - return S_OK; -} - -static HRESULT WINAPI DSoundRender_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum) -{ - DSoundRenderImpl *This = (DSoundRenderImpl *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum); - - return IEnumPinsImpl_Construct(ppEnum, DSoundRender_GetPin, iface); -} - -static HRESULT WINAPI DSoundRender_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin) -{ - DSoundRenderImpl *This = (DSoundRenderImpl *)iface; - - TRACE("(%p/%p)->(%s,%p)\n", This, iface, debugstr_w(Id), ppPin); - - FIXME("DSoundRender::FindPin(...)\n"); - - /* FIXME: critical section */ - - return E_NOTIMPL; -} - -static HRESULT WINAPI DSoundRender_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo) -{ - DSoundRenderImpl *This = (DSoundRenderImpl *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, pInfo); - - strcpyW(pInfo->achName, This->filterInfo.achName); - pInfo->pGraph = This->filterInfo.pGraph; - - if (pInfo->pGraph) - IFilterGraph_AddRef(pInfo->pGraph); - - return S_OK; -} - -static HRESULT WINAPI DSoundRender_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName) -{ - DSoundRenderImpl *This = (DSoundRenderImpl *)iface; - - TRACE("(%p/%p)->(%p, %s)\n", This, iface, pGraph, debugstr_w(pName)); - - EnterCriticalSection(&This->csFilter); - { - if (pName) - strcpyW(This->filterInfo.achName, pName); - else - *This->filterInfo.achName = '\0'; - This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */ - } - LeaveCriticalSection(&This->csFilter); - - return S_OK; -} - -static HRESULT WINAPI DSoundRender_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo) -{ - DSoundRenderImpl *This = (DSoundRenderImpl *)iface; - TRACE("(%p/%p)->(%p)\n", This, iface, pVendorInfo); - return E_NOTIMPL; -} - static const IBaseFilterVtbl DSoundRender_Vtbl = { DSoundRender_QueryInterface, - DSoundRender_AddRef, + BaseFilterImpl_AddRef, DSoundRender_Release, - DSoundRender_GetClassID, - DSoundRender_Stop, + BaseFilterImpl_GetClassID, + BaseRendererImpl_Stop, DSoundRender_Pause, - DSoundRender_Run, - DSoundRender_GetState, - DSoundRender_SetSyncSource, - DSoundRender_GetSyncSource, - DSoundRender_EnumPins, - DSoundRender_FindPin, - DSoundRender_QueryFilterInfo, - DSoundRender_JoinFilterGraph, - DSoundRender_QueryVendorInfo -}; - -static HRESULT WINAPI DSoundRender_InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) -{ - InputPin *This = (InputPin *)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.fnQueryAccept(This->pin.pUserData, 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 DSoundRender_InputPin_Disconnect(IPin * iface) -{ - IPinImpl *This = (IPinImpl*)iface; - DSoundRenderImpl *DSImpl; - - TRACE("(%p)->()\n", iface); - - DSImpl = (DSoundRenderImpl*)This->pinInfo.pFilter; - if (DSImpl->dsbuffer) - IDirectSoundBuffer_Release(DSImpl->dsbuffer); - DSImpl->dsbuffer = NULL; - - return IPinImpl_Disconnect(iface); -} - -static HRESULT WINAPI DSoundRender_InputPin_EndOfStream(IPin * iface) -{ - InputPin* This = (InputPin*)iface; - DSoundRenderImpl *me = (DSoundRenderImpl*)This->pin.pinInfo.pFilter; - IMediaEventSink* pEventSink; - HRESULT hr; - - EnterCriticalSection(This->pin.pCritSec); - - TRACE("(%p/%p)->()\n", This, iface); - hr = InputPin_EndOfStream(iface); - if (hr != S_OK) - { - ERR("%08x\n", hr); - LeaveCriticalSection(This->pin.pCritSec); - return hr; - } - - hr = IFilterGraph_QueryInterface(me->filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink); - if (SUCCEEDED(hr)) - { - BYTE * silence; - - silence = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, me->buf_size); - if (silence) - { - memset(silence, 0, me->buf_size); - DSoundRender_SendSampleData((DSoundRenderImpl*)This->pin.pinInfo.pFilter, silence, me->buf_size); - HeapFree(GetProcessHeap(), 0, silence); - } - - hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, 0); - IMediaEventSink_Release(pEventSink); - } - LeaveCriticalSection(This->pin.pCritSec); - - return hr; -} - -static HRESULT WINAPI DSoundRender_InputPin_BeginFlush(IPin * iface) -{ - InputPin *This = (InputPin *)iface; - DSoundRenderImpl *pFilter = (DSoundRenderImpl *)This->pin.pinInfo.pFilter; - HRESULT hr; - LPBYTE buffer; - DWORD size; - - TRACE("\n"); - - EnterCriticalSection(This->pin.pCritSec); - hr = InputPin_BeginFlush(iface); - - if (pFilter->dsbuffer) - { - IDirectSoundBuffer_Stop(pFilter->dsbuffer); - - /* Force a reset */ - IDirectSoundBuffer_SetCurrentPosition(pFilter->dsbuffer, 0); - pFilter->write_pos = pFilter->last_play_pos = 0; - ++pFilter->play_loops; - pFilter->write_loops = pFilter->play_loops; - - IDirectSoundBuffer_Lock(pFilter->dsbuffer, 0, 0, (LPVOID *)&buffer, &size, NULL, NULL, DSBLOCK_ENTIREBUFFER); - memset(buffer, 0, size); - IDirectSoundBuffer_Unlock(pFilter->dsbuffer, buffer, size, NULL, 0); - } - - if (pFilter->state == State_Paused) - SetEvent(pFilter->blocked); - LeaveCriticalSection(This->pin.pCritSec); - - return hr; -} - -static HRESULT WINAPI DSoundRender_InputPin_EndFlush(IPin * iface) -{ - InputPin *This = (InputPin *)iface; - DSoundRenderImpl *pFilter = (DSoundRenderImpl *)This->pin.pinInfo.pFilter; - HRESULT hr; - - TRACE("\n"); - - EnterCriticalSection(This->pin.pCritSec); - hr = InputPin_EndFlush(iface); - - if (pFilter->state == State_Paused) - SetEvent(pFilter->blocked); - LeaveCriticalSection(This->pin.pCritSec); - - return hr; -} - -static const IPinVtbl DSoundRender_InputPin_Vtbl = -{ - InputPin_QueryInterface, - IPinImpl_AddRef, - InputPin_Release, - InputPin_Connect, - DSoundRender_InputPin_ReceiveConnection, - DSoundRender_InputPin_Disconnect, - IPinImpl_ConnectedTo, - IPinImpl_ConnectionMediaType, - IPinImpl_QueryPinInfo, - IPinImpl_QueryDirection, - IPinImpl_QueryId, - IPinImpl_QueryAccept, - IPinImpl_EnumMediaTypes, - IPinImpl_QueryInternalConnections, - DSoundRender_InputPin_EndOfStream, - DSoundRender_InputPin_BeginFlush, - DSoundRender_InputPin_EndFlush, - InputPin_NewSegment + BaseRendererImpl_Run, + BaseRendererImpl_GetState, + BaseRendererImpl_SetSyncSource, + BaseFilterImpl_GetSyncSource, + BaseFilterImpl_EnumPins, + BaseRendererImpl_FindPin, + BaseFilterImpl_QueryFilterInfo, + BaseFilterImpl_JoinFilterGraph, + BaseFilterImpl_QueryVendorInfo }; /*** IUnknown methods ***/ static HRESULT WINAPI Basicaudio_QueryInterface(IBasicAudio *iface, REFIID riid, LPVOID*ppvObj) { - ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface); + DSoundRenderImpl *This = impl_from_IBasicAudio(iface); TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); - return DSoundRender_QueryInterface((IBaseFilter*)This, riid, ppvObj); + return DSoundRender_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppvObj); } static ULONG WINAPI Basicaudio_AddRef(IBasicAudio *iface) { - ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface); + DSoundRenderImpl *This = impl_from_IBasicAudio(iface); TRACE("(%p/%p)->()\n", This, iface); - return DSoundRender_AddRef((IBaseFilter*)This); + return BaseFilterImpl_AddRef(&This->renderer.filter.IBaseFilter_iface); } static ULONG WINAPI Basicaudio_Release(IBasicAudio *iface) { - ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface); + DSoundRenderImpl *This = impl_from_IBasicAudio(iface); TRACE("(%p/%p)->()\n", This, iface); - return DSoundRender_Release((IBaseFilter*)This); -} - -/*** IDispatch methods ***/ -static HRESULT WINAPI Basicaudio_GetTypeInfoCount(IBasicAudio *iface, - UINT*pctinfo) { - ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface); - - TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo); - - return S_OK; -} - -static HRESULT WINAPI Basicaudio_GetTypeInfo(IBasicAudio *iface, - UINT iTInfo, - LCID lcid, - ITypeInfo**ppTInfo) { - ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface); - - TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo); - - return S_OK; -} - -static HRESULT WINAPI Basicaudio_GetIDsOfNames(IBasicAudio *iface, - REFIID riid, - LPOLESTR*rgszNames, - UINT cNames, - LCID lcid, - DISPID*rgDispId) { - ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface); - - TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId); - - return S_OK; -} - -static HRESULT WINAPI Basicaudio_Invoke(IBasicAudio *iface, - DISPID dispIdMember, - REFIID riid, - LCID lcid, - WORD wFlags, - DISPPARAMS*pDispParams, - VARIANT*pVarResult, - EXCEPINFO*pExepInfo, - UINT*puArgErr) { - ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface); - - TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr); - - return S_OK; + return DSoundRender_Release(&This->renderer.filter.IBaseFilter_iface); } /*** IBasicAudio methods ***/ static HRESULT WINAPI Basicaudio_put_Volume(IBasicAudio *iface, LONG lVolume) { - ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface); + DSoundRenderImpl *This = impl_from_IBasicAudio(iface); TRACE("(%p/%p)->(%d)\n", This, iface, lVolume); @@ -1132,7 +849,7 @@ static HRESULT WINAPI Basicaudio_put_Volume(IBasicAudio *iface, static HRESULT WINAPI Basicaudio_get_Volume(IBasicAudio *iface, LONG *plVolume) { - ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface); + DSoundRenderImpl *This = impl_from_IBasicAudio(iface); TRACE("(%p/%p)->(%p)\n", This, iface, plVolume); @@ -1145,7 +862,7 @@ static HRESULT WINAPI Basicaudio_get_Volume(IBasicAudio *iface, static HRESULT WINAPI Basicaudio_put_Balance(IBasicAudio *iface, LONG lBalance) { - ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface); + DSoundRenderImpl *This = impl_from_IBasicAudio(iface); TRACE("(%p/%p)->(%d)\n", This, iface, lBalance); @@ -1163,7 +880,7 @@ static HRESULT WINAPI Basicaudio_put_Balance(IBasicAudio *iface, static HRESULT WINAPI Basicaudio_get_Balance(IBasicAudio *iface, LONG *plBalance) { - ICOM_THIS_MULTI(DSoundRenderImpl, IBasicAudio_vtbl, iface); + DSoundRenderImpl *This = impl_from_IBasicAudio(iface); TRACE("(%p/%p)->(%p)\n", This, iface, plBalance); @@ -1179,61 +896,163 @@ static const IBasicAudioVtbl IBasicAudio_Vtbl = Basicaudio_QueryInterface, Basicaudio_AddRef, Basicaudio_Release, - Basicaudio_GetTypeInfoCount, - Basicaudio_GetTypeInfo, - Basicaudio_GetIDsOfNames, - Basicaudio_Invoke, + BasicAudioImpl_GetTypeInfoCount, + BasicAudioImpl_GetTypeInfo, + BasicAudioImpl_GetIDsOfNames, + BasicAudioImpl_Invoke, Basicaudio_put_Volume, Basicaudio_get_Volume, Basicaudio_put_Balance, Basicaudio_get_Balance }; +struct dsoundrender_timer { + struct dsoundrender_timer *next; + REFERENCE_TIME start; + REFERENCE_TIME periodicity; + HANDLE handle; + DWORD cookie; +}; +static LONG cookie_counter = 1; + +static DWORD WINAPI DSoundAdviseThread(LPVOID lpParam) { + DSoundRenderImpl *This = lpParam; + struct dsoundrender_timer head = {0}; + MSG msg; + + TRACE("(%p): Main Loop\n", This); + + PeekMessageW(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); + SetEvent(This->thread_wait); + + while (1) + { + HRESULT hr; + REFERENCE_TIME curtime = 0; + BOOL ret; + struct dsoundrender_timer *prev = &head, *cur; + + hr = IReferenceClock_GetTime(&This->IReferenceClock_iface, &curtime); + if (SUCCEEDED(hr)) { + TRACE("Time: %s\n", wine_dbgstr_longlong(curtime)); + while (prev->next) { + cur = prev->next; + if (cur->start > curtime) { + TRACE("Skipping %p\n", cur); + prev = cur; + } else if (cur->periodicity) { + while (cur->start <= curtime) { + cur->start += cur->periodicity; + ReleaseSemaphore(cur->handle, 1, NULL); + } + prev = cur; + } else { + struct dsoundrender_timer *next = cur->next; + TRACE("Firing %p %s < %s\n", cur, wine_dbgstr_longlong(cur->start), wine_dbgstr_longlong(curtime)); + SetEvent(cur->handle); + HeapFree(GetProcessHeap(), 0, cur); + prev->next = next; + } + } + } + if (!head.next) + ret = GetMessageW(&msg, INVALID_HANDLE_VALUE, WM_APP, WM_APP + 4); + else + ret = PeekMessageW(&msg, INVALID_HANDLE_VALUE, WM_APP, WM_APP + 4, PM_REMOVE); + while (ret) { + switch (LOWORD(msg.message) - WM_APP) { + case 0: TRACE("Exiting\n"); return 0; + case 1: + case 2: { + struct dsoundrender_timer *t = (struct dsoundrender_timer *)msg.wParam; + if (LOWORD(msg.message) - WM_APP == 1) + TRACE("Adding one-shot timer %p\n", t); + else + TRACE("Adding periodic timer %p\n", t); + t->next = head.next; + head.next = t; + break; + } + case 3: + prev = &head; + while (prev->next) { + cur = prev->next; + if (cur->cookie == msg.wParam) { + struct dsoundrender_timer *next = cur->next; + HeapFree(GetProcessHeap(), 0, cur); + prev->next = next; + break; + } + prev = cur; + } + break; + } + ret = PeekMessageW(&msg, INVALID_HANDLE_VALUE, WM_APP, WM_APP + 4, PM_REMOVE); + } + MsgWaitForMultipleObjects(0, NULL, 5, QS_POSTMESSAGE, 0); + } + return 0; +} /*** IUnknown methods ***/ static HRESULT WINAPI ReferenceClock_QueryInterface(IReferenceClock *iface, REFIID riid, LPVOID*ppvObj) { - ICOM_THIS_MULTI(DSoundRenderImpl, IReferenceClock_vtbl, iface); + DSoundRenderImpl *This = impl_from_IReferenceClock(iface); TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); - return DSoundRender_QueryInterface((IBaseFilter*)This, riid, ppvObj); + return DSoundRender_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppvObj); } static ULONG WINAPI ReferenceClock_AddRef(IReferenceClock *iface) { - ICOM_THIS_MULTI(DSoundRenderImpl, IReferenceClock_vtbl, iface); + DSoundRenderImpl *This = impl_from_IReferenceClock(iface); TRACE("(%p/%p)->()\n", This, iface); - return DSoundRender_AddRef((IBaseFilter*)This); + return BaseFilterImpl_AddRef(&This->renderer.filter.IBaseFilter_iface); } static ULONG WINAPI ReferenceClock_Release(IReferenceClock *iface) { - ICOM_THIS_MULTI(DSoundRenderImpl, IReferenceClock_vtbl, iface); + DSoundRenderImpl *This = impl_from_IReferenceClock(iface); TRACE("(%p/%p)->()\n", This, iface); - return DSoundRender_Release((IBaseFilter*)This); + return DSoundRender_Release(&This->renderer.filter.IBaseFilter_iface); } /*** IReferenceClock methods ***/ static HRESULT WINAPI ReferenceClock_GetTime(IReferenceClock *iface, REFERENCE_TIME *pTime) { - ICOM_THIS_MULTI(DSoundRenderImpl, IReferenceClock_vtbl, iface); + DSoundRenderImpl *This = impl_from_IReferenceClock(iface); HRESULT hr = E_FAIL; - DWORD play_pos; TRACE("(%p/%p)->(%p)\n", This, iface, pTime); + if (!pTime) + return E_POINTER; - if (This->dsbuffer) - hr = DSoundRender_GetPos(This, &play_pos, pTime); + if (This->dsbuffer) { + DWORD writepos1, writepos2; + EnterCriticalSection(&This->renderer.filter.csFilter); + DSoundRender_UpdatePositions(This, &writepos1, &writepos2); + if (This->renderer.pInputPin && This->renderer.pInputPin->pin.mtCurrent.pbFormat) + { + *pTime = This->play_time + time_from_pos(This, This->last_playpos); + hr = S_OK; + } + else + { + ERR("pInputPin Disconncted\n"); + hr = E_FAIL; + } + LeaveCriticalSection(&This->renderer.filter.csFilter); + } if (FAILED(hr)) - ERR("Could not get reference time (%x)!\n", hr); + WARN("Could not get reference time (%x)!\n", hr); return hr; } @@ -1244,34 +1063,92 @@ static HRESULT WINAPI ReferenceClock_AdviseTime(IReferenceClock *iface, HEVENT hEvent, DWORD_PTR *pdwAdviseCookie) { - ICOM_THIS_MULTI(DSoundRenderImpl, IReferenceClock_vtbl, iface); + DSoundRenderImpl *This = impl_from_IReferenceClock(iface); + REFERENCE_TIME when = rtBaseTime + rtStreamTime; + REFERENCE_TIME future; + TRACE("(%p/%p)->(%s, %s, %p, %p)\n", This, iface, wine_dbgstr_longlong(rtBaseTime), wine_dbgstr_longlong(rtStreamTime), (void*)hEvent, pdwAdviseCookie); - FIXME("(%p/%p)->(%s, %s, %p, %p): stub!\n", This, iface, wine_dbgstr_longlong(rtBaseTime), wine_dbgstr_longlong(rtStreamTime), (void*)hEvent, pdwAdviseCookie); + if (when <= 0) + return E_INVALIDARG; - return E_NOTIMPL; + if (!pdwAdviseCookie) + return E_POINTER; + + EnterCriticalSection(&This->renderer.filter.csFilter); + future = when - This->play_time; + if (!This->threadid && This->dsbuffer) { + This->thread_wait = CreateEventW(0, 0, 0, 0); + This->advisethread = CreateThread(NULL, 0, DSoundAdviseThread, This, 0, &This->threadid); + WaitForSingleObject(This->thread_wait, INFINITE); + CloseHandle(This->thread_wait); + } + LeaveCriticalSection(&This->renderer.filter.csFilter); + /* If it's in the past or the next millisecond, trigger immediately */ + if (future <= 10000) { + SetEvent((HANDLE)hEvent); + *pdwAdviseCookie = 0; + } else { + struct dsoundrender_timer *t = HeapAlloc(GetProcessHeap(), 0, sizeof(*t)); + t->next = NULL; + t->start = when; + t->periodicity = 0; + t->handle = (HANDLE)hEvent; + t->cookie = InterlockedIncrement(&cookie_counter); + PostThreadMessageW(This->threadid, WM_APP+1, (WPARAM)t, 0); + *pdwAdviseCookie = t->cookie; + } + + return S_OK; } static HRESULT WINAPI ReferenceClock_AdvisePeriodic(IReferenceClock *iface, - REFERENCE_TIME rtBaseTime, - REFERENCE_TIME rtStreamTime, + REFERENCE_TIME rtStartTime, + REFERENCE_TIME rtPeriodTime, HSEMAPHORE hSemaphore, DWORD_PTR *pdwAdviseCookie) { - ICOM_THIS_MULTI(DSoundRenderImpl, IReferenceClock_vtbl, iface); + DSoundRenderImpl *This = impl_from_IReferenceClock(iface); + struct dsoundrender_timer *t; - FIXME("(%p/%p)->(%s, %s, %p, %p): stub!\n", This, iface, wine_dbgstr_longlong(rtBaseTime), wine_dbgstr_longlong(rtStreamTime), (void*)hSemaphore, pdwAdviseCookie); + TRACE("(%p/%p)->(%s, %s, %p, %p)\n", This, iface, wine_dbgstr_longlong(rtStartTime), wine_dbgstr_longlong(rtPeriodTime), (void*)hSemaphore, pdwAdviseCookie); - return E_NOTIMPL; + if (rtStartTime <= 0 || rtPeriodTime <= 0) + return E_INVALIDARG; + + if (!pdwAdviseCookie) + return E_POINTER; + + EnterCriticalSection(&This->renderer.filter.csFilter); + if (!This->threadid && This->dsbuffer) { + This->thread_wait = CreateEventW(0, 0, 0, 0); + This->advisethread = CreateThread(NULL, 0, DSoundAdviseThread, This, 0, &This->threadid); + WaitForSingleObject(This->thread_wait, INFINITE); + CloseHandle(This->thread_wait); + } + LeaveCriticalSection(&This->renderer.filter.csFilter); + + t = HeapAlloc(GetProcessHeap(), 0, sizeof(*t)); + t->next = NULL; + t->start = rtStartTime; + t->periodicity = rtPeriodTime; + t->handle = (HANDLE)hSemaphore; + t->cookie = InterlockedIncrement(&cookie_counter); + PostThreadMessageW(This->threadid, WM_APP+1, (WPARAM)t, 0); + *pdwAdviseCookie = t->cookie; + + return S_OK; } static HRESULT WINAPI ReferenceClock_Unadvise(IReferenceClock *iface, DWORD_PTR dwAdviseCookie) { - ICOM_THIS_MULTI(DSoundRenderImpl, IReferenceClock_vtbl, iface); + DSoundRenderImpl *This = impl_from_IReferenceClock(iface); - FIXME("(%p/%p)->(%p): stub!\n", This, iface, (void*)dwAdviseCookie); - - return S_FALSE; + TRACE("(%p/%p)->(%p)\n", This, iface, (void*)dwAdviseCookie); + if (!This->advisethread || !dwAdviseCookie) + return S_FALSE; + PostThreadMessageW(This->threadid, WM_APP+3, dwAdviseCookie, 0); + return S_OK; } static const IReferenceClockVtbl IReferenceClock_Vtbl = @@ -1285,90 +1162,40 @@ static const IReferenceClockVtbl IReferenceClock_Vtbl = ReferenceClock_Unadvise }; -static inline DSoundRenderImpl *impl_from_IMediaSeeking( IMediaSeeking *iface ) -{ - return (DSoundRenderImpl *)((char*)iface - FIELD_OFFSET(DSoundRenderImpl, mediaSeeking.lpVtbl)); -} - -static HRESULT WINAPI sound_seek_QueryInterface(IMediaSeeking * iface, REFIID riid, LPVOID * ppv) -{ - DSoundRenderImpl *This = impl_from_IMediaSeeking(iface); - - return IUnknown_QueryInterface((IUnknown *)This, riid, ppv); -} - -static ULONG WINAPI sound_seek_AddRef(IMediaSeeking * iface) -{ - DSoundRenderImpl *This = impl_from_IMediaSeeking(iface); - - return IUnknown_AddRef((IUnknown *)This); -} - -static ULONG WINAPI sound_seek_Release(IMediaSeeking * iface) -{ - DSoundRenderImpl *This = impl_from_IMediaSeeking(iface); - - return IUnknown_Release((IUnknown *)This); -} - -static const IMediaSeekingVtbl IMediaSeeking_Vtbl = -{ - sound_seek_QueryInterface, - sound_seek_AddRef, - sound_seek_Release, - MediaSeekingImpl_GetCapabilities, - MediaSeekingImpl_CheckCapabilities, - MediaSeekingImpl_IsFormatSupported, - MediaSeekingImpl_QueryPreferredFormat, - MediaSeekingImpl_GetTimeFormat, - MediaSeekingImpl_IsUsingTimeFormat, - MediaSeekingImpl_SetTimeFormat, - MediaSeekingImpl_GetDuration, - MediaSeekingImpl_GetStopPosition, - MediaSeekingImpl_GetCurrentPosition, - MediaSeekingImpl_ConvertTimeFormat, - MediaSeekingImpl_SetPositions, - MediaSeekingImpl_GetPositions, - MediaSeekingImpl_GetAvailable, - MediaSeekingImpl_SetRate, - MediaSeekingImpl_GetRate, - MediaSeekingImpl_GetPreroll -}; - /*** IUnknown methods ***/ static HRESULT WINAPI AMDirectSound_QueryInterface(IAMDirectSound *iface, REFIID riid, LPVOID*ppvObj) { - ICOM_THIS_MULTI(DSoundRenderImpl, IAMDirectSound_vtbl, iface); + DSoundRenderImpl *This = impl_from_IAMDirectSound(iface); TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); - return DSoundRender_QueryInterface((IBaseFilter*)This, riid, ppvObj); + return DSoundRender_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppvObj); } static ULONG WINAPI AMDirectSound_AddRef(IAMDirectSound *iface) { - ICOM_THIS_MULTI(DSoundRenderImpl, IAMDirectSound_vtbl, iface); + DSoundRenderImpl *This = impl_from_IAMDirectSound(iface); TRACE("(%p/%p)->()\n", This, iface); - return DSoundRender_AddRef((IBaseFilter*)This); + return BaseFilterImpl_AddRef(&This->renderer.filter.IBaseFilter_iface); } static ULONG WINAPI AMDirectSound_Release(IAMDirectSound *iface) { - ICOM_THIS_MULTI(DSoundRenderImpl, IAMDirectSound_vtbl, iface); + DSoundRenderImpl *This = impl_from_IAMDirectSound(iface); TRACE("(%p/%p)->()\n", This, iface); - return DSoundRender_Release((IBaseFilter*)This); + return DSoundRender_Release(&This->renderer.filter.IBaseFilter_iface); } /*** IAMDirectSound methods ***/ static HRESULT WINAPI AMDirectSound_GetDirectSoundInterface(IAMDirectSound *iface, IDirectSound **ds) { - ICOM_THIS_MULTI(DSoundRenderImpl, IAMDirectSound_vtbl, iface); + DSoundRenderImpl *This = impl_from_IAMDirectSound(iface); FIXME("(%p/%p)->(%p): stub\n", This, iface, ds); @@ -1377,7 +1204,7 @@ static HRESULT WINAPI AMDirectSound_GetDirectSoundInterface(IAMDirectSound *ifac static HRESULT WINAPI AMDirectSound_GetPrimaryBufferInterface(IAMDirectSound *iface, IDirectSoundBuffer **buf) { - ICOM_THIS_MULTI(DSoundRenderImpl, IAMDirectSound_vtbl, iface); + DSoundRenderImpl *This = impl_from_IAMDirectSound(iface); FIXME("(%p/%p)->(%p): stub\n", This, iface, buf); @@ -1386,7 +1213,7 @@ static HRESULT WINAPI AMDirectSound_GetPrimaryBufferInterface(IAMDirectSound *if static HRESULT WINAPI AMDirectSound_GetSecondaryBufferInterface(IAMDirectSound *iface, IDirectSoundBuffer **buf) { - ICOM_THIS_MULTI(DSoundRenderImpl, IAMDirectSound_vtbl, iface); + DSoundRenderImpl *This = impl_from_IAMDirectSound(iface); FIXME("(%p/%p)->(%p): stub\n", This, iface, buf); @@ -1395,7 +1222,7 @@ static HRESULT WINAPI AMDirectSound_GetSecondaryBufferInterface(IAMDirectSound * static HRESULT WINAPI AMDirectSound_ReleaseDirectSoundInterface(IAMDirectSound *iface, IDirectSound *ds) { - ICOM_THIS_MULTI(DSoundRenderImpl, IAMDirectSound_vtbl, iface); + DSoundRenderImpl *This = impl_from_IAMDirectSound(iface); FIXME("(%p/%p)->(%p): stub\n", This, iface, ds); @@ -1404,7 +1231,7 @@ static HRESULT WINAPI AMDirectSound_ReleaseDirectSoundInterface(IAMDirectSound * static HRESULT WINAPI AMDirectSound_ReleasePrimaryBufferInterface(IAMDirectSound *iface, IDirectSoundBuffer *buf) { - ICOM_THIS_MULTI(DSoundRenderImpl, IAMDirectSound_vtbl, iface); + DSoundRenderImpl *This = impl_from_IAMDirectSound(iface); FIXME("(%p/%p)->(%p): stub\n", This, iface, buf); @@ -1413,7 +1240,7 @@ static HRESULT WINAPI AMDirectSound_ReleasePrimaryBufferInterface(IAMDirectSound static HRESULT WINAPI AMDirectSound_ReleaseSecondaryBufferInterface(IAMDirectSound *iface, IDirectSoundBuffer *buf) { - ICOM_THIS_MULTI(DSoundRenderImpl, IAMDirectSound_vtbl, iface); + DSoundRenderImpl *This = impl_from_IAMDirectSound(iface); FIXME("(%p/%p)->(%p): stub\n", This, iface, buf); @@ -1422,7 +1249,7 @@ static HRESULT WINAPI AMDirectSound_ReleaseSecondaryBufferInterface(IAMDirectSou static HRESULT WINAPI AMDirectSound_SetFocusWindow(IAMDirectSound *iface, HWND hwnd, BOOL bgsilent) { - ICOM_THIS_MULTI(DSoundRenderImpl, IAMDirectSound_vtbl, iface); + DSoundRenderImpl *This = impl_from_IAMDirectSound(iface); FIXME("(%p/%p)->(%p,%d): stub\n", This, iface, hwnd, bgsilent); @@ -1431,7 +1258,7 @@ static HRESULT WINAPI AMDirectSound_SetFocusWindow(IAMDirectSound *iface, HWND h static HRESULT WINAPI AMDirectSound_GetFocusWindow(IAMDirectSound *iface, HWND hwnd) { - ICOM_THIS_MULTI(DSoundRenderImpl, IAMDirectSound_vtbl, iface); + DSoundRenderImpl *This = impl_from_IAMDirectSound(iface); FIXME("(%p/%p)->(%p): stub\n", This, iface, hwnd); @@ -1452,3 +1279,29 @@ static const IAMDirectSoundVtbl IAMDirectSound_Vtbl = AMDirectSound_SetFocusWindow, AMDirectSound_GetFocusWindow }; + +static HRESULT WINAPI AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid, void **ppv) { + DSoundRenderImpl *This = impl_from_IAMFilterMiscFlags(iface); + return IUnknown_QueryInterface((IUnknown*)This, riid, ppv); +} + +static ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface) { + DSoundRenderImpl *This = impl_from_IAMFilterMiscFlags(iface); + return IUnknown_AddRef((IUnknown*)This); +} + +static ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface) { + DSoundRenderImpl *This = impl_from_IAMFilterMiscFlags(iface); + return IUnknown_Release((IUnknown*)This); +} + +static ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface) { + return AM_FILTER_MISC_FLAGS_IS_RENDERER; +} + +static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = { + AMFilterMiscFlags_QueryInterface, + AMFilterMiscFlags_AddRef, + AMFilterMiscFlags_Release, + AMFilterMiscFlags_GetMiscFlags +}; diff --git a/reactos/dll/directx/quartz/enumfilters.c b/reactos/dll/directx/quartz/enumfilters.c index ad80e619564..5182e6a8ddd 100644 --- a/reactos/dll/directx/quartz/enumfilters.c +++ b/reactos/dll/directx/quartz/enumfilters.c @@ -26,22 +26,31 @@ WINE_DEFAULT_DEBUG_CHANNEL(quartz); typedef struct IEnumFiltersImpl { - const IEnumFiltersVtbl * lpVtbl; + IEnumFilters IEnumFilters_iface; LONG refCount; - IBaseFilter ** ppFilters; - int nFilters; + IGraphVersion * pVersionSource; + LONG Version; + IBaseFilter *** pppFilters; + ULONG * pNumFilters; ULONG uIndex; } IEnumFiltersImpl; static const struct IEnumFiltersVtbl IEnumFiltersImpl_Vtbl; -HRESULT IEnumFiltersImpl_Construct(IBaseFilter ** ppFilters, ULONG nFilters, IEnumFilters ** ppEnum) +static inline IEnumFiltersImpl *impl_from_IEnumFilters(IEnumFilters *iface) +{ + return CONTAINING_RECORD(iface, IEnumFiltersImpl, IEnumFilters_iface); +} + +HRESULT IEnumFiltersImpl_Construct(IGraphVersion * pVersionSource, IBaseFilter *** pppFilters, ULONG * pNumFilters, IEnumFilters ** ppEnum) { /* Note: The incoming IBaseFilter interfaces are not AddRef'd here as in Windows, * they should have been previously AddRef'd. */ IEnumFiltersImpl * pEnumFilters = CoTaskMemAlloc(sizeof(IEnumFiltersImpl)); + HRESULT hr; + LONG currentVersion; - TRACE("(%p, %d, %p)\n", ppFilters, nFilters, ppEnum); + TRACE("(%p, %p, %p)\n", pppFilters, pNumFilters, ppEnum); *ppEnum = NULL; @@ -50,20 +59,19 @@ HRESULT IEnumFiltersImpl_Construct(IBaseFilter ** ppFilters, ULONG nFilters, IEn return E_OUTOFMEMORY; } - pEnumFilters->lpVtbl = &IEnumFiltersImpl_Vtbl; + pEnumFilters->IEnumFilters_iface.lpVtbl = &IEnumFiltersImpl_Vtbl; pEnumFilters->refCount = 1; pEnumFilters->uIndex = 0; - pEnumFilters->nFilters = nFilters; - pEnumFilters->ppFilters = CoTaskMemAlloc(sizeof(IBaseFilter*) * nFilters); - if (!pEnumFilters->ppFilters) - { - CoTaskMemFree(pEnumFilters); - return E_OUTOFMEMORY; - } + pEnumFilters->pNumFilters = pNumFilters; + pEnumFilters->pppFilters = pppFilters; + IGraphVersion_AddRef(pVersionSource); + pEnumFilters->pVersionSource = pVersionSource; - memcpy(pEnumFilters->ppFilters, ppFilters, nFilters * sizeof(IBaseFilter*)); + /* Store the current version of the graph */ + hr = IGraphVersion_QueryVersion(pVersionSource, ¤tVersion); + pEnumFilters->Version = (hr==S_OK) ? currentVersion : 0; - *ppEnum = (IEnumFilters *)(&pEnumFilters->lpVtbl); + *ppEnum = &pEnumFilters->IEnumFilters_iface; return S_OK; } @@ -91,7 +99,7 @@ static HRESULT WINAPI IEnumFiltersImpl_QueryInterface(IEnumFilters * iface, REFI static ULONG WINAPI IEnumFiltersImpl_AddRef(IEnumFilters * iface) { - IEnumFiltersImpl *This = (IEnumFiltersImpl *)iface; + IEnumFiltersImpl *This = impl_from_IEnumFilters(iface); ULONG refCount = InterlockedIncrement(&This->refCount); TRACE("(%p)->()\n", iface); @@ -101,15 +109,14 @@ static ULONG WINAPI IEnumFiltersImpl_AddRef(IEnumFilters * iface) static ULONG WINAPI IEnumFiltersImpl_Release(IEnumFilters * iface) { - IEnumFiltersImpl *This = (IEnumFiltersImpl *)iface; + IEnumFiltersImpl *This = impl_from_IEnumFilters(iface); ULONG refCount = InterlockedDecrement(&This->refCount); TRACE("(%p)->()\n", iface); if (!refCount) { - CoTaskMemFree(This->ppFilters); - CoTaskMemFree(This); + IGraphVersion_Release(This->pVersionSource); return 0; } else @@ -120,18 +127,26 @@ static HRESULT WINAPI IEnumFiltersImpl_Next(IEnumFilters * iface, ULONG cFilters { ULONG cFetched; ULONG i; - IEnumFiltersImpl *This = (IEnumFiltersImpl *)iface; + LONG currentVersion; + IEnumFiltersImpl *This = impl_from_IEnumFilters(iface); + HRESULT hr; - cFetched = min(This->nFilters, This->uIndex + cFilters) - This->uIndex; + cFetched = min(*This->pNumFilters, This->uIndex + cFilters) - This->uIndex; TRACE("(%p)->(%u, %p, %p)\n", iface, cFilters, ppFilters, pcFetched); + /* First of all check if the graph has changed */ + hr = IGraphVersion_QueryVersion(This->pVersionSource, ¤tVersion); + if (hr==S_OK && This->Version != currentVersion) + return VFW_E_ENUM_OUT_OF_SYNC; + + if (!ppFilters) return E_POINTER; for (i = 0; i < cFetched; i++) { - ppFilters[i] = This->ppFilters[This->uIndex + i]; + ppFilters[i] = (*This->pppFilters)[This->uIndex + i]; IBaseFilter_AddRef(ppFilters[i]); } @@ -147,11 +162,11 @@ static HRESULT WINAPI IEnumFiltersImpl_Next(IEnumFilters * iface, ULONG cFilters static HRESULT WINAPI IEnumFiltersImpl_Skip(IEnumFilters * iface, ULONG cFilters) { - IEnumFiltersImpl *This = (IEnumFiltersImpl *)iface; + IEnumFiltersImpl *This = impl_from_IEnumFilters(iface); TRACE("(%p)->(%u)\n", iface, cFilters); - if (This->uIndex + cFilters < This->nFilters) + if (This->uIndex + cFilters < *This->pNumFilters) { This->uIndex += cFilters; return S_OK; @@ -161,22 +176,27 @@ static HRESULT WINAPI IEnumFiltersImpl_Skip(IEnumFilters * iface, ULONG cFilters static HRESULT WINAPI IEnumFiltersImpl_Reset(IEnumFilters * iface) { - IEnumFiltersImpl *This = (IEnumFiltersImpl *)iface; + IEnumFiltersImpl *This = impl_from_IEnumFilters(iface); + HRESULT hr; + LONG currentVersion; TRACE("(%p)->()\n", iface); This->uIndex = 0; + hr = IGraphVersion_QueryVersion(This->pVersionSource, ¤tVersion); + if (!hr) + This->Version = currentVersion; return S_OK; } static HRESULT WINAPI IEnumFiltersImpl_Clone(IEnumFilters * iface, IEnumFilters ** ppEnum) { HRESULT hr; - IEnumFiltersImpl *This = (IEnumFiltersImpl *)iface; + IEnumFiltersImpl *This = impl_from_IEnumFilters(iface); TRACE("(%p)->(%p)\n", iface, ppEnum); - hr = IEnumFiltersImpl_Construct(This->ppFilters, This->nFilters, ppEnum); + hr = IEnumFiltersImpl_Construct(This->pVersionSource, This->pppFilters, This->pNumFilters, ppEnum); if (FAILED(hr)) return hr; return IEnumFilters_Skip(*ppEnum, This->uIndex); diff --git a/reactos/dll/directx/quartz/enummedia.c b/reactos/dll/directx/quartz/enummedia.c index fca46912121..fab473663d8 100644 --- a/reactos/dll/directx/quartz/enummedia.c +++ b/reactos/dll/directx/quartz/enummedia.c @@ -24,237 +24,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(quartz); -HRESULT CopyMediaType(AM_MEDIA_TYPE * pDest, const AM_MEDIA_TYPE *pSrc) -{ - *pDest = *pSrc; - if (!pSrc->pbFormat) return S_OK; - if (!(pDest->pbFormat = CoTaskMemAlloc(pSrc->cbFormat))) - return E_OUTOFMEMORY; - memcpy(pDest->pbFormat, pSrc->pbFormat, pSrc->cbFormat); - if (pDest->pUnk) - IUnknown_AddRef(pDest->pUnk); - return S_OK; -} - -void FreeMediaType(AM_MEDIA_TYPE * pMediaType) -{ - if (pMediaType->pbFormat) - { - CoTaskMemFree(pMediaType->pbFormat); - pMediaType->pbFormat = NULL; - } - if (pMediaType->pUnk) - { - IUnknown_Release(pMediaType->pUnk); - pMediaType->pUnk = NULL; - } -} - -static AM_MEDIA_TYPE * CreateMediaType(AM_MEDIA_TYPE const * pSrc) -{ - AM_MEDIA_TYPE * pDest; - - pDest = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE)); - if (!pDest) - return NULL; - - if (FAILED(CopyMediaType(pDest, pSrc))) - { - CoTaskMemFree(pDest); - return NULL; - } - - return pDest; -} - -void DeleteMediaType(AM_MEDIA_TYPE * pMediaType) -{ - FreeMediaType(pMediaType); - CoTaskMemFree(pMediaType); -} - -BOOL CompareMediaTypes(const AM_MEDIA_TYPE * pmt1, const AM_MEDIA_TYPE * pmt2, BOOL bWildcards) -{ - TRACE("pmt1: "); - dump_AM_MEDIA_TYPE(pmt1); - TRACE("pmt2: "); - dump_AM_MEDIA_TYPE(pmt2); - return (((bWildcards && (IsEqualGUID(&pmt1->majortype, &GUID_NULL) || IsEqualGUID(&pmt2->majortype, &GUID_NULL))) || IsEqualGUID(&pmt1->majortype, &pmt2->majortype)) && - ((bWildcards && (IsEqualGUID(&pmt1->subtype, &GUID_NULL) || IsEqualGUID(&pmt2->subtype, &GUID_NULL))) || IsEqualGUID(&pmt1->subtype, &pmt2->subtype))); -} - void dump_AM_MEDIA_TYPE(const AM_MEDIA_TYPE * pmt) { if (!pmt) return; TRACE("\t%s\n\t%s\n\t...\n\t%s\n", qzdebugstr_guid(&pmt->majortype), qzdebugstr_guid(&pmt->subtype), qzdebugstr_guid(&pmt->formattype)); } - -typedef struct IEnumMediaTypesImpl -{ - const IEnumMediaTypesVtbl * lpVtbl; - LONG refCount; - ENUMMEDIADETAILS enumMediaDetails; - ULONG uIndex; -} IEnumMediaTypesImpl; - -static const struct IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl; - -HRESULT IEnumMediaTypesImpl_Construct(const ENUMMEDIADETAILS * pDetails, IEnumMediaTypes ** ppEnum) -{ - ULONG i; - IEnumMediaTypesImpl * pEnumMediaTypes = CoTaskMemAlloc(sizeof(IEnumMediaTypesImpl)); - - if (!pEnumMediaTypes) - { - *ppEnum = NULL; - return E_OUTOFMEMORY; - } - pEnumMediaTypes->lpVtbl = &IEnumMediaTypesImpl_Vtbl; - pEnumMediaTypes->refCount = 1; - pEnumMediaTypes->uIndex = 0; - pEnumMediaTypes->enumMediaDetails.cMediaTypes = pDetails->cMediaTypes; - pEnumMediaTypes->enumMediaDetails.pMediaTypes = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * pDetails->cMediaTypes); - for (i = 0; i < pDetails->cMediaTypes; i++) - if (FAILED(CopyMediaType(&pEnumMediaTypes->enumMediaDetails.pMediaTypes[i], &pDetails->pMediaTypes[i]))) - { - while (i--) - CoTaskMemFree(pEnumMediaTypes->enumMediaDetails.pMediaTypes[i].pbFormat); - CoTaskMemFree(pEnumMediaTypes->enumMediaDetails.pMediaTypes); - return E_OUTOFMEMORY; - } - *ppEnum = (IEnumMediaTypes *)(&pEnumMediaTypes->lpVtbl); - return S_OK; -} - -static HRESULT WINAPI IEnumMediaTypesImpl_QueryInterface(IEnumMediaTypes * iface, REFIID riid, LPVOID * ppv) -{ - TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv); - - *ppv = NULL; - - if (IsEqualIID(riid, &IID_IUnknown)) - *ppv = iface; - else if (IsEqualIID(riid, &IID_IEnumMediaTypes)) - *ppv = iface; - - if (*ppv) - { - IUnknown_AddRef((IUnknown *)(*ppv)); - return S_OK; - } - - FIXME("No interface for %s!\n", qzdebugstr_guid(riid)); - - return E_NOINTERFACE; -} - -static ULONG WINAPI IEnumMediaTypesImpl_AddRef(IEnumMediaTypes * iface) -{ - IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface; - ULONG refCount = InterlockedIncrement(&This->refCount); - - TRACE("(%p)->() AddRef from %d\n", iface, refCount - 1); - - return refCount; -} - -static ULONG WINAPI IEnumMediaTypesImpl_Release(IEnumMediaTypes * iface) -{ - IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface; - ULONG refCount = InterlockedDecrement(&This->refCount); - - TRACE("(%p)->() Release from %d\n", iface, refCount + 1); - - if (!refCount) - { - ULONG i; - for (i = 0; i < This->enumMediaDetails.cMediaTypes; i++) - if (This->enumMediaDetails.pMediaTypes[i].pbFormat) - CoTaskMemFree(This->enumMediaDetails.pMediaTypes[i].pbFormat); - CoTaskMemFree(This->enumMediaDetails.pMediaTypes); - CoTaskMemFree(This); - } - return refCount; -} - -static HRESULT WINAPI IEnumMediaTypesImpl_Next(IEnumMediaTypes * iface, ULONG cMediaTypes, AM_MEDIA_TYPE ** ppMediaTypes, ULONG * pcFetched) -{ - ULONG cFetched; - IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface; - - cFetched = min(This->enumMediaDetails.cMediaTypes, This->uIndex + cMediaTypes) - This->uIndex; - - TRACE("(%u, %p, %p)\n", cMediaTypes, ppMediaTypes, pcFetched); - TRACE("Next uIndex: %u, cFetched: %u\n", This->uIndex, cFetched); - - if (cFetched > 0) - { - ULONG i; - for (i = 0; i < cFetched; i++) - if (!(ppMediaTypes[i] = CreateMediaType(&This->enumMediaDetails.pMediaTypes[This->uIndex + i]))) - { - while (i--) - DeleteMediaType(ppMediaTypes[i]); - *pcFetched = 0; - return E_OUTOFMEMORY; - } - } - - if ((cMediaTypes != 1) || pcFetched) - *pcFetched = cFetched; - - This->uIndex += cFetched; - - if (cFetched != cMediaTypes) - return S_FALSE; - return S_OK; -} - -static HRESULT WINAPI IEnumMediaTypesImpl_Skip(IEnumMediaTypes * iface, ULONG cMediaTypes) -{ - IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface; - - TRACE("(%u)\n", cMediaTypes); - - if (This->uIndex + cMediaTypes < This->enumMediaDetails.cMediaTypes) - { - This->uIndex += cMediaTypes; - return S_OK; - } - return S_FALSE; -} - -static HRESULT WINAPI IEnumMediaTypesImpl_Reset(IEnumMediaTypes * iface) -{ - IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface; - - TRACE("()\n"); - - This->uIndex = 0; - return S_OK; -} - -static HRESULT WINAPI IEnumMediaTypesImpl_Clone(IEnumMediaTypes * iface, IEnumMediaTypes ** ppEnum) -{ - HRESULT hr; - IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface; - - TRACE("(%p)\n", ppEnum); - - hr = IEnumMediaTypesImpl_Construct(&This->enumMediaDetails, ppEnum); - if (FAILED(hr)) - return hr; - return IEnumMediaTypes_Skip(*ppEnum, This->uIndex); -} - -static const IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl = -{ - IEnumMediaTypesImpl_QueryInterface, - IEnumMediaTypesImpl_AddRef, - IEnumMediaTypesImpl_Release, - IEnumMediaTypesImpl_Next, - IEnumMediaTypesImpl_Skip, - IEnumMediaTypesImpl_Reset, - IEnumMediaTypesImpl_Clone -}; diff --git a/reactos/dll/directx/quartz/enummoniker.c b/reactos/dll/directx/quartz/enummoniker.c index 55f4d6a8d03..b3561374e9c 100644 --- a/reactos/dll/directx/quartz/enummoniker.c +++ b/reactos/dll/directx/quartz/enummoniker.c @@ -3,9 +3,6 @@ * * Copyright 2003 Robert Shearman * - * This file contains the (internal) driver registration functions, - * driver enumeration APIs and DirectDraw creation functions. - * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -31,7 +28,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(quartz); typedef struct EnumMonikerImpl { - const IEnumMonikerVtbl *lpVtbl; + IEnumMoniker IEnumMoniker_iface; LONG ref; IMoniker ** ppMoniker; ULONG nMonikerCount; @@ -40,6 +37,11 @@ typedef struct EnumMonikerImpl static const IEnumMonikerVtbl EnumMonikerImpl_Vtbl; +static inline EnumMonikerImpl *impl_from_IEnumMoniker(IEnumMoniker *iface) +{ + return CONTAINING_RECORD(iface, EnumMonikerImpl, IEnumMoniker_iface); +} + static ULONG WINAPI EnumMonikerImpl_AddRef(LPENUMMONIKER iface); HRESULT EnumMonikerImpl_Create(IMoniker ** ppMoniker, ULONG nMonikerCount, IEnumMoniker ** ppEnum) @@ -56,14 +58,14 @@ HRESULT EnumMonikerImpl_Create(IMoniker ** ppMoniker, ULONG nMonikerCount, IEnum if (!pemi) return E_OUTOFMEMORY; - pemi->lpVtbl = &EnumMonikerImpl_Vtbl; + pemi->IEnumMoniker_iface.lpVtbl = &EnumMonikerImpl_Vtbl; pemi->ref = 1; pemi->ppMoniker = CoTaskMemAlloc(nMonikerCount * sizeof(IMoniker*)); memcpy(pemi->ppMoniker, ppMoniker, nMonikerCount*sizeof(IMoniker*)); pemi->nMonikerCount = nMonikerCount; pemi->index = 0; - *ppEnum = (IEnumMoniker *)pemi; + *ppEnum = &pemi->IEnumMoniker_iface; return S_OK; } @@ -76,7 +78,7 @@ static HRESULT WINAPI EnumMonikerImpl_QueryInterface( REFIID riid, LPVOID *ppvObj) { - EnumMonikerImpl *This = (EnumMonikerImpl *)iface; + EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); TRACE("\n\tIID:\t%s\n",debugstr_guid(riid)); if (This == NULL || ppvObj == NULL) return E_POINTER; @@ -99,7 +101,7 @@ static HRESULT WINAPI EnumMonikerImpl_QueryInterface( */ static ULONG WINAPI EnumMonikerImpl_AddRef(LPENUMMONIKER iface) { - EnumMonikerImpl *This = (EnumMonikerImpl *)iface; + EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); ULONG ref; if (This == NULL) return E_POINTER; @@ -116,7 +118,7 @@ static ULONG WINAPI EnumMonikerImpl_AddRef(LPENUMMONIKER iface) */ static ULONG WINAPI EnumMonikerImpl_Release(LPENUMMONIKER iface) { - EnumMonikerImpl *This = (EnumMonikerImpl *)iface; + EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p)->() Release from %d\n", iface, ref + 1); @@ -139,7 +141,7 @@ static ULONG WINAPI EnumMonikerImpl_Release(LPENUMMONIKER iface) static HRESULT WINAPI EnumMonikerImpl_Next(LPENUMMONIKER iface, ULONG celt, IMoniker ** rgelt, ULONG * pceltFetched) { ULONG fetched; - EnumMonikerImpl *This = (EnumMonikerImpl *)iface; + EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); TRACE("(%p)->(%d, %p, %p)\n", iface, celt, rgelt, pceltFetched); @@ -164,7 +166,7 @@ static HRESULT WINAPI EnumMonikerImpl_Next(LPENUMMONIKER iface, ULONG celt, IMon static HRESULT WINAPI EnumMonikerImpl_Skip(LPENUMMONIKER iface, ULONG celt) { - EnumMonikerImpl *This = (EnumMonikerImpl *)iface; + EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); TRACE("(%p)->(%d)\n", iface, celt); @@ -175,7 +177,7 @@ static HRESULT WINAPI EnumMonikerImpl_Skip(LPENUMMONIKER iface, ULONG celt) static HRESULT WINAPI EnumMonikerImpl_Reset(LPENUMMONIKER iface) { - EnumMonikerImpl *This = (EnumMonikerImpl *)iface; + EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); TRACE("(%p)->()\n", iface); diff --git a/reactos/dll/directx/quartz/enumregfilters.c b/reactos/dll/directx/quartz/enumregfilters.c index 7145778b251..b5c92ba4b46 100644 --- a/reactos/dll/directx/quartz/enumregfilters.c +++ b/reactos/dll/directx/quartz/enumregfilters.c @@ -28,13 +28,18 @@ WINE_DEFAULT_DEBUG_CHANNEL(quartz); typedef struct IEnumRegFiltersImpl { - const IEnumRegFiltersVtbl * lpVtbl; + IEnumRegFilters IEnumRegFilters_iface; LONG refCount; ULONG size; REGFILTER* RegFilters; ULONG uIndex; } IEnumRegFiltersImpl; +static inline IEnumRegFiltersImpl *impl_from_IEnumRegFilters(IEnumRegFilters *iface) +{ + return CONTAINING_RECORD(iface, IEnumRegFiltersImpl, IEnumRegFilters_iface); +} + static const struct IEnumRegFiltersVtbl IEnumRegFiltersImpl_Vtbl; HRESULT IEnumRegFiltersImpl_Construct(REGFILTER* pInRegFilters, const ULONG size, IEnumRegFilters ** ppEnum) @@ -79,13 +84,13 @@ HRESULT IEnumRegFiltersImpl_Construct(REGFILTER* pInRegFilters, const ULONG size CopyMemory(pRegFilters[i].Name, pInRegFilters[i].Name, (strlenW(pInRegFilters[i].Name)+1)*sizeof(WCHAR)); } - pEnumRegFilters->lpVtbl = &IEnumRegFiltersImpl_Vtbl; + pEnumRegFilters->IEnumRegFilters_iface.lpVtbl = &IEnumRegFiltersImpl_Vtbl; pEnumRegFilters->refCount = 1; pEnumRegFilters->uIndex = 0; pEnumRegFilters->RegFilters = pRegFilters; pEnumRegFilters->size = size; - *ppEnum = (IEnumRegFilters *)(&pEnumRegFilters->lpVtbl); + *ppEnum = &pEnumRegFilters->IEnumRegFilters_iface; return S_OK; } @@ -114,7 +119,7 @@ static HRESULT WINAPI IEnumRegFiltersImpl_QueryInterface(IEnumRegFilters * iface static ULONG WINAPI IEnumRegFiltersImpl_AddRef(IEnumRegFilters * iface) { - IEnumRegFiltersImpl *This = (IEnumRegFiltersImpl *)iface; + IEnumRegFiltersImpl *This = impl_from_IEnumRegFilters(iface); ULONG refCount = InterlockedIncrement(&This->refCount); TRACE("(%p)\n", iface); @@ -124,7 +129,7 @@ static ULONG WINAPI IEnumRegFiltersImpl_AddRef(IEnumRegFilters * iface) static ULONG WINAPI IEnumRegFiltersImpl_Release(IEnumRegFilters * iface) { - IEnumRegFiltersImpl *This = (IEnumRegFiltersImpl *)iface; + IEnumRegFiltersImpl *This = impl_from_IEnumRegFilters(iface); ULONG refCount = InterlockedDecrement(&This->refCount); TRACE("(%p)\n", iface); @@ -147,7 +152,7 @@ static ULONG WINAPI IEnumRegFiltersImpl_Release(IEnumRegFilters * iface) static HRESULT WINAPI IEnumRegFiltersImpl_Next(IEnumRegFilters * iface, ULONG cFilters, REGFILTER ** ppRegFilter, ULONG * pcFetched) { ULONG cFetched; - IEnumRegFiltersImpl *This = (IEnumRegFiltersImpl *)iface; + IEnumRegFiltersImpl *This = impl_from_IEnumRegFilters(iface); unsigned int i; cFetched = min(This->size, This->uIndex + cFilters) - This->uIndex; @@ -193,7 +198,7 @@ static HRESULT WINAPI IEnumRegFiltersImpl_Skip(IEnumRegFilters * iface, ULONG n) static HRESULT WINAPI IEnumRegFiltersImpl_Reset(IEnumRegFilters * iface) { - IEnumRegFiltersImpl *This = (IEnumRegFiltersImpl *)iface; + IEnumRegFiltersImpl *This = impl_from_IEnumRegFilters(iface); TRACE("(%p)\n", iface); diff --git a/reactos/dll/directx/quartz/fil_data.idl b/reactos/dll/directx/quartz/fil_data.idl new file mode 100644 index 00000000000..93cdf1e43dd --- /dev/null +++ b/reactos/dll/directx/quartz/fil_data.idl @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2009 Vitaliy Margolen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +import "objidl.idl"; +import "strmif.idl"; +import "unknwn.idl"; + + +/***************************************************************************** + * IAMFilterData interface + * + * Notes: + * - This interface is deprecated and IFilterMapper2 should be used instead. + * - There is no full replacement for IAMFilterData::ParseFilterData short of manually + * parsing out the REGFILTER2 struct from the binary blob. + */ +[ + object, + uuid(97f7c4d4-547b-4a5f-8332-536430ad2e4d), + pointer_default(unique) +] +interface IAMFilterData : IUnknown +{ + typedef [unique] IAMFilterData *LPIAMFILTERDATA; + + HRESULT ParseFilterData( + [in] BYTE * rgbFilterData, + [in] ULONG cb, + [out] BYTE ** prgbRegFilter2); + + HRESULT CreateFilterData( + [in] REGFILTER2 * prf2, + [out] BYTE ** prgbFilterData, + [out] ULONG * pcb); +} diff --git a/reactos/dll/directx/quartz/filesource.c b/reactos/dll/directx/quartz/filesource.c index 6f1174d5924..75023019409 100644 --- a/reactos/dll/directx/quartz/filesource.c +++ b/reactos/dll/directx/quartz/filesource.c @@ -39,37 +39,50 @@ static const WCHAR wszOutputPinName[] = { 'O','u','t','p','u','t',0 }; typedef struct AsyncReader { - const IBaseFilterVtbl * lpVtbl; - const IFileSourceFilterVtbl * lpVtblFSF; - - LONG refCount; - FILTER_INFO filterInfo; - FILTER_STATE state; - CRITICAL_SECTION csFilter; - DWORD lastpinchange; + BaseFilter filter; + IFileSourceFilter IFileSourceFilter_iface; + IAMFilterMiscFlags IAMFilterMiscFlags_iface; IPin * pOutputPin; LPOLESTR pszFileName; AM_MEDIA_TYPE * pmt; } AsyncReader; +static inline AsyncReader *impl_from_BaseFilter(BaseFilter *iface) +{ + return CONTAINING_RECORD(iface, AsyncReader, filter); +} + +static inline AsyncReader *impl_from_IBaseFilter(IBaseFilter *iface) +{ + return CONTAINING_RECORD(iface, AsyncReader, filter.IBaseFilter_iface); +} + +static inline AsyncReader *impl_from_IFileSourceFilter(IFileSourceFilter *iface) +{ + return CONTAINING_RECORD(iface, AsyncReader, IFileSourceFilter_iface); +} + +static inline AsyncReader *impl_from_IAMFilterMiscFlags(IAMFilterMiscFlags *iface) +{ + return CONTAINING_RECORD(iface, AsyncReader, IAMFilterMiscFlags_iface); +} + static const IBaseFilterVtbl AsyncReader_Vtbl; static const IFileSourceFilterVtbl FileSource_Vtbl; static const IAsyncReaderVtbl FileAsyncReader_Vtbl; +static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl; static HRESULT FileAsyncReader_Construct(HANDLE hFile, IBaseFilter * pBaseFilter, LPCRITICAL_SECTION pCritSec, IPin ** ppPin); -static inline AsyncReader *impl_from_IFileSourceFilter( IFileSourceFilter *iface ) -{ - return (AsyncReader *)((char*)iface - FIELD_OFFSET(AsyncReader, lpVtblFSF)); -} - -static WCHAR const mediatype_name[11] = { +static const WCHAR mediatype_name[] = { 'M', 'e', 'd', 'i', 'a', ' ', 'T', 'y', 'p', 'e', 0 }; -static WCHAR const subtype_name[8] = { +static const WCHAR subtype_name[] = { 'S', 'u', 'b', 't', 'y', 'p', 'e', 0 }; +static const WCHAR source_filter_name[] = { + 'S','o','u','r','c','e',' ','F','i','l','t','e','r',0}; -static HRESULT process_extensions(HKEY hkeyExtensions, LPCOLESTR pszFileName, GUID * majorType, GUID * minorType) +static HRESULT process_extensions(HKEY hkeyExtensions, LPCOLESTR pszFileName, GUID * majorType, GUID * minorType, GUID * sourceFilter) { WCHAR *extension; LONG l; @@ -89,17 +102,31 @@ static HRESULT process_extensions(HKEY hkeyExtensions, LPCOLESTR pszFileName, GU if (l) return E_FAIL; - size = sizeof(keying); - l = RegQueryValueExW(hsub, mediatype_name, NULL, NULL, (LPBYTE)keying, &size); - if (!l) - CLSIDFromString(keying, majorType); + if (majorType) + { + size = sizeof(keying); + l = RegQueryValueExW(hsub, mediatype_name, NULL, NULL, (LPBYTE)keying, &size); + if (!l) + CLSIDFromString(keying, majorType); + } - size = sizeof(keying); - if (!l) - l = RegQueryValueExW(hsub, subtype_name, NULL, NULL, (LPBYTE)keying, &size); + if (minorType) + { + size = sizeof(keying); + if (!l) + l = RegQueryValueExW(hsub, subtype_name, NULL, NULL, (LPBYTE)keying, &size); + if (!l) + CLSIDFromString(keying, minorType); + } - if (!l) - CLSIDFromString(keying, minorType); + if (sourceFilter) + { + size = sizeof(keying); + if (!l) + l = RegQueryValueExW(hsub, source_filter_name, NULL, NULL, (LPBYTE)keying, &size); + if (!l) + CLSIDFromString(keying, sourceFilter); + } RegCloseKey(hsub); @@ -183,8 +210,8 @@ static HRESULT process_pattern_string(LPCWSTR wszPatternString, IAsyncReader * p if (!(wszPatternString = strchrW(wszPatternString, ','))) hr = E_INVALIDARG; - - wszPatternString++; /* skip ',' */ + else + wszPatternString++; /* skip ',' */ } if (hr == S_OK) @@ -227,7 +254,7 @@ static HRESULT process_pattern_string(LPCWSTR wszPatternString, IAsyncReader * p return hr; } -static HRESULT GetClassMediaFile(IAsyncReader * pReader, LPCOLESTR pszFileName, GUID * majorType, GUID * minorType) +HRESULT GetClassMediaFile(IAsyncReader * pReader, LPCOLESTR pszFileName, GUID * majorType, GUID * minorType, GUID * sourceFilter) { HKEY hkeyMediaType = NULL; LONG lRet; @@ -237,8 +264,12 @@ static HRESULT GetClassMediaFile(IAsyncReader * pReader, LPCOLESTR pszFileName, TRACE("(%p, %s, %p, %p)\n", pReader, debugstr_w(pszFileName), majorType, minorType); - *majorType = GUID_NULL; - *minorType = GUID_NULL; + if(majorType) + *majorType = GUID_NULL; + if(minorType) + *minorType = GUID_NULL; + if(sourceFilter) + *sourceFilter = GUID_NULL; lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszMediaType, 0, KEY_READ, &hkeyMediaType); hr = HRESULT_FROM_WIN32(lRet); @@ -261,10 +292,11 @@ static HRESULT GetClassMediaFile(IAsyncReader * pReader, LPCOLESTR pszFileName, TRACE("%s\n", debugstr_w(wszMajorKeyName)); if (!strcmpW(wszExtensions, wszMajorKeyName)) { - if (process_extensions(hkeyMajor, pszFileName, majorType, minorType) == S_OK) + if (process_extensions(hkeyMajor, pszFileName, majorType, minorType, sourceFilter) == S_OK) bFound = TRUE; } - else + /* We need a reader interface to check bytes */ + else if (pReader) { DWORD indexMinor; @@ -273,6 +305,8 @@ static HRESULT GetClassMediaFile(IAsyncReader * pReader, LPCOLESTR pszFileName, HKEY hkeyMinor; WCHAR wszMinorKeyName[CHARS_IN_GUID]; DWORD dwMinorKeyNameLen = sizeof(wszMinorKeyName) / sizeof(wszMinorKeyName[0]); + WCHAR wszSourceFilterKeyName[CHARS_IN_GUID]; + DWORD dwSourceFilterKeyNameLen = sizeof(wszSourceFilterKeyName); DWORD maxValueLen; DWORD indexValue; @@ -294,26 +328,37 @@ static HRESULT GetClassMediaFile(IAsyncReader * pReader, LPCOLESTR pszFileName, LPWSTR wszPatternString = HeapAlloc(GetProcessHeap(), 0, maxValueLen); DWORD dwValueNameLen = sizeof(wszValueName) / sizeof(wszValueName[0]); /* remember this is in chars */ DWORD dwDataLen = maxValueLen; /* remember this is in bytes */ - static const WCHAR wszSourceFilter[] = {'S','o','u','r','c','e',' ','F','i','l','t','e','r',0}; - LONG temp; - if ((temp = RegEnumValueW(hkeyMinor, indexValue, wszValueName, &dwValueNameLen, NULL, &dwType, (LPBYTE)wszPatternString, &dwDataLen)) != ERROR_SUCCESS) + if (RegEnumValueW(hkeyMinor, indexValue, wszValueName, &dwValueNameLen, NULL, &dwType, (LPBYTE)wszPatternString, &dwDataLen) != ERROR_SUCCESS) { HeapFree(GetProcessHeap(), 0, wszPatternString); break; } - /* if it is not the source filter value */ - if (strcmpW(wszValueName, wszSourceFilter)) - { - if (process_pattern_string(wszPatternString, pReader) == S_OK) - { - if (SUCCEEDED(CLSIDFromString(wszMajorKeyName, majorType)) && - SUCCEEDED(CLSIDFromString(wszMinorKeyName, minorType))) - bFound = TRUE; - } + if (strcmpW(wszValueName, source_filter_name)==0) { + HeapFree(GetProcessHeap(), 0, wszPatternString); + continue; } - HeapFree(GetProcessHeap(), 0, wszPatternString); + + /* if it is not the source filter value */ + if (process_pattern_string(wszPatternString, pReader) == S_OK) + { + HeapFree(GetProcessHeap(), 0, wszPatternString); + if (majorType && FAILED(CLSIDFromString(wszMajorKeyName, majorType))) + break; + if (minorType && FAILED(CLSIDFromString(wszMinorKeyName, minorType))) + break; + if (sourceFilter) + { + /* Look up the source filter key */ + if (RegQueryValueExW(hkeyMinor, source_filter_name, NULL, NULL, (LPBYTE)wszSourceFilterKeyName, &dwSourceFilterKeyNameLen)) + break; + if (FAILED(CLSIDFromString(wszSourceFilterKeyName, sourceFilter))) + break; + } + bFound = TRUE; + } else + HeapFree(GetProcessHeap(), 0, wszPatternString); } CloseHandle(hkeyMinor); } @@ -329,11 +374,45 @@ static HRESULT GetClassMediaFile(IAsyncReader * pReader, LPCOLESTR pszFileName, hr = E_FAIL; } else if (bFound) - TRACE("Found file's class: major = %s, subtype = %s\n", qzdebugstr_guid(majorType), qzdebugstr_guid(minorType)); + { + TRACE("Found file's class:\n"); + if(majorType) + TRACE("\tmajor = %s\n", qzdebugstr_guid(majorType)); + if(minorType) + TRACE("\tsubtype = %s\n", qzdebugstr_guid(minorType)); + if(sourceFilter) + TRACE("\tsource filter = %s\n", qzdebugstr_guid(sourceFilter)); + } return hr; } +static IPin* WINAPI AsyncReader_GetPin(BaseFilter *iface, int pos) +{ + AsyncReader *This = impl_from_BaseFilter(iface); + + if (pos >= 1 || !This->pOutputPin) + return NULL; + + IPin_AddRef(This->pOutputPin); + return This->pOutputPin; +} + +static LONG WINAPI AsyncReader_GetPinCount(BaseFilter *iface) +{ + AsyncReader *This = impl_from_BaseFilter(iface); + + if (!This->pOutputPin) + return 0; + else + return 1; +} + +static const BaseFilterFuncTable BaseFuncTable = { + AsyncReader_GetPin, + AsyncReader_GetPinCount +}; + HRESULT AsyncReader_create(IUnknown * pUnkOuter, LPVOID * ppv) { AsyncReader *pAsyncRead; @@ -346,17 +425,11 @@ HRESULT AsyncReader_create(IUnknown * pUnkOuter, LPVOID * ppv) if (!pAsyncRead) return E_OUTOFMEMORY; - pAsyncRead->lpVtbl = &AsyncReader_Vtbl; - pAsyncRead->lpVtblFSF = &FileSource_Vtbl; - pAsyncRead->refCount = 1; - pAsyncRead->filterInfo.achName[0] = '\0'; - pAsyncRead->filterInfo.pGraph = NULL; - pAsyncRead->pOutputPin = NULL; - pAsyncRead->lastpinchange = GetTickCount(); - pAsyncRead->state = State_Stopped; + BaseFilter_Init(&pAsyncRead->filter, &AsyncReader_Vtbl, &CLSID_AsyncReader, (DWORD_PTR)(__FILE__ ": AsyncReader.csFilter"), &BaseFuncTable); - InitializeCriticalSection(&pAsyncRead->csFilter); - pAsyncRead->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": AsyncReader.csFilter"); + pAsyncRead->IFileSourceFilter_iface.lpVtbl = &FileSource_Vtbl; + pAsyncRead->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_Vtbl; + pAsyncRead->pOutputPin = NULL; pAsyncRead->pszFileName = NULL; pAsyncRead->pmt = NULL; @@ -372,7 +445,7 @@ HRESULT AsyncReader_create(IUnknown * pUnkOuter, LPVOID * ppv) static HRESULT WINAPI AsyncReader_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv) { - AsyncReader *This = (AsyncReader *)iface; + AsyncReader *This = impl_from_IBaseFilter(iface); TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv); @@ -387,7 +460,9 @@ static HRESULT WINAPI AsyncReader_QueryInterface(IBaseFilter * iface, REFIID rii else if (IsEqualIID(riid, &IID_IBaseFilter)) *ppv = This; else if (IsEqualIID(riid, &IID_IFileSourceFilter)) - *ppv = &This->lpVtblFSF; + *ppv = &This->IFileSourceFilter_iface; + else if (IsEqualIID(riid, &IID_IAMFilterMiscFlags)) + *ppv = &This->IAMFilterMiscFlags_iface; if (*ppv) { @@ -402,20 +477,10 @@ static HRESULT WINAPI AsyncReader_QueryInterface(IBaseFilter * iface, REFIID rii return E_NOINTERFACE; } -static ULONG WINAPI AsyncReader_AddRef(IBaseFilter * iface) -{ - AsyncReader *This = (AsyncReader *)iface; - ULONG refCount = InterlockedIncrement(&This->refCount); - - TRACE("(%p)->() AddRef from %d\n", This, refCount - 1); - - return refCount; -} - static ULONG WINAPI AsyncReader_Release(IBaseFilter * iface) { - AsyncReader *This = (AsyncReader *)iface; - ULONG refCount = InterlockedDecrement(&This->refCount); + AsyncReader *This = impl_from_IBaseFilter(iface); + ULONG refCount = BaseFilterImpl_Release(iface); TRACE("(%p)->() Release from %d\n", This, refCount + 1); @@ -432,9 +497,6 @@ static ULONG WINAPI AsyncReader_Release(IBaseFilter * iface) IPin_Disconnect(This->pOutputPin); IPin_Release(This->pOutputPin); } - This->csFilter.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&This->csFilter); - This->lpVtbl = NULL; CoTaskMemFree(This->pszFileName); if (This->pmt) FreeMediaType(This->pmt); @@ -445,189 +507,100 @@ static ULONG WINAPI AsyncReader_Release(IBaseFilter * iface) return refCount; } -/** IPersist methods **/ - -static HRESULT WINAPI AsyncReader_GetClassID(IBaseFilter * iface, CLSID * pClsid) -{ - TRACE("(%p)\n", pClsid); - - *pClsid = CLSID_AsyncReader; - - return S_OK; -} - /** IMediaFilter methods **/ static HRESULT WINAPI AsyncReader_Stop(IBaseFilter * iface) { - AsyncReader *This = (AsyncReader *)iface; + AsyncReader *This = impl_from_IBaseFilter(iface); TRACE("()\n"); - This->state = State_Stopped; + This->filter.state = State_Stopped; return S_OK; } static HRESULT WINAPI AsyncReader_Pause(IBaseFilter * iface) { - AsyncReader *This = (AsyncReader *)iface; + AsyncReader *This = impl_from_IBaseFilter(iface); TRACE("()\n"); - This->state = State_Paused; + This->filter.state = State_Paused; return S_OK; } static HRESULT WINAPI AsyncReader_Run(IBaseFilter * iface, REFERENCE_TIME tStart) { - AsyncReader *This = (AsyncReader *)iface; + AsyncReader *This = impl_from_IBaseFilter(iface); TRACE("(%x%08x)\n", (ULONG)(tStart >> 32), (ULONG)tStart); - This->state = State_Running; - - return S_OK; -} - -static HRESULT WINAPI AsyncReader_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState) -{ - AsyncReader *This = (AsyncReader *)iface; - - TRACE("(%u, %p)\n", dwMilliSecsTimeout, pState); - - *pState = This->state; - - return S_OK; -} - -static HRESULT WINAPI AsyncReader_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock) -{ -/* AsyncReader *This = (AsyncReader *)iface;*/ - - TRACE("(%p)\n", pClock); - - return S_OK; -} - -static HRESULT WINAPI AsyncReader_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock) -{ -/* AsyncReader *This = (AsyncReader *)iface;*/ - - TRACE("(%p)\n", ppClock); + This->filter.state = State_Running; return S_OK; } /** IBaseFilter methods **/ -static HRESULT AsyncReader_GetPin(IBaseFilter *iface, ULONG pos, IPin **pin, DWORD *lastsynctick) -{ - AsyncReader *This = (AsyncReader *)iface; - - /* Our pins are almost static, not changing so setting static tick count is ok */ - *lastsynctick = This->lastpinchange; - - if (pos >= 1 || !This->pOutputPin) - return S_FALSE; - - *pin = This->pOutputPin; - IPin_AddRef(*pin); - return S_OK; -} - -static HRESULT WINAPI AsyncReader_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum) -{ - AsyncReader *This = (AsyncReader *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum); - - return IEnumPinsImpl_Construct(ppEnum, AsyncReader_GetPin, iface); -} - static HRESULT WINAPI AsyncReader_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin) { - FIXME("(%s, %p)\n", debugstr_w(Id), ppPin); + AsyncReader *This = impl_from_IBaseFilter(iface); + TRACE("(%s, %p)\n", debugstr_w(Id), ppPin); - return E_NOTIMPL; -} + if (!Id || !ppPin) + return E_POINTER; -static HRESULT WINAPI AsyncReader_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo) -{ - AsyncReader *This = (AsyncReader *)iface; + if (strcmpW(Id, wszOutputPinName)) + { + *ppPin = NULL; + return VFW_E_NOT_FOUND; + } - TRACE("(%p)\n", pInfo); - - strcpyW(pInfo->achName, This->filterInfo.achName); - pInfo->pGraph = This->filterInfo.pGraph; - - if (pInfo->pGraph) - IFilterGraph_AddRef(pInfo->pGraph); - + *ppPin = This->pOutputPin; + IPin_AddRef(*ppPin); return S_OK; } -static HRESULT WINAPI AsyncReader_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName) -{ - AsyncReader *This = (AsyncReader *)iface; - - TRACE("(%p, %s)\n", pGraph, debugstr_w(pName)); - - if (pName) - strcpyW(This->filterInfo.achName, pName); - else - *This->filterInfo.achName = 0; - This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */ - - return S_OK; -} - -static HRESULT WINAPI AsyncReader_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo) -{ - FIXME("(%p)\n", pVendorInfo); - - return E_NOTIMPL; -} - static const IBaseFilterVtbl AsyncReader_Vtbl = { AsyncReader_QueryInterface, - AsyncReader_AddRef, + BaseFilterImpl_AddRef, AsyncReader_Release, - AsyncReader_GetClassID, + BaseFilterImpl_GetClassID, AsyncReader_Stop, AsyncReader_Pause, AsyncReader_Run, - AsyncReader_GetState, - AsyncReader_SetSyncSource, - AsyncReader_GetSyncSource, - AsyncReader_EnumPins, + BaseFilterImpl_GetState, + BaseFilterImpl_SetSyncSource, + BaseFilterImpl_GetSyncSource, + BaseFilterImpl_EnumPins, AsyncReader_FindPin, - AsyncReader_QueryFilterInfo, - AsyncReader_JoinFilterGraph, - AsyncReader_QueryVendorInfo + BaseFilterImpl_QueryFilterInfo, + BaseFilterImpl_JoinFilterGraph, + BaseFilterImpl_QueryVendorInfo }; static HRESULT WINAPI FileSource_QueryInterface(IFileSourceFilter * iface, REFIID riid, LPVOID * ppv) { AsyncReader *This = impl_from_IFileSourceFilter(iface); - return IBaseFilter_QueryInterface((IFileSourceFilter*)&This->lpVtbl, riid, ppv); + return IBaseFilter_QueryInterface(&This->filter.IBaseFilter_iface, riid, ppv); } static ULONG WINAPI FileSource_AddRef(IFileSourceFilter * iface) { AsyncReader *This = impl_from_IFileSourceFilter(iface); - return IBaseFilter_AddRef((IFileSourceFilter*)&This->lpVtbl); + return IBaseFilter_AddRef(&This->filter.IBaseFilter_iface); } static ULONG WINAPI FileSource_Release(IFileSourceFilter * iface) { AsyncReader *This = impl_from_IFileSourceFilter(iface); - return IBaseFilter_Release((IFileSourceFilter*)&This->lpVtbl); + return IBaseFilter_Release(&This->filter.IBaseFilter_iface); } static HRESULT WINAPI FileSource_Load(IFileSourceFilter * iface, LPCOLESTR pszFileName, const AM_MEDIA_TYPE * pmt) @@ -649,8 +622,8 @@ static HRESULT WINAPI FileSource_Load(IFileSourceFilter * iface, LPCOLESTR pszFi } /* create pin */ - hr = FileAsyncReader_Construct(hFile, (IBaseFilter *)&This->lpVtbl, &This->csFilter, &This->pOutputPin); - This->lastpinchange = GetTickCount(); + hr = FileAsyncReader_Construct(hFile, &This->filter.IBaseFilter_iface, &This->filter.csFilter, &This->pOutputPin); + BaseFilterImpl_IncrementPinVersion(&This->filter); if (SUCCEEDED(hr)) hr = IPin_QueryInterface(This->pOutputPin, &IID_IAsyncReader, (LPVOID *)&pReader); @@ -675,7 +648,7 @@ static HRESULT WINAPI FileSource_Load(IFileSourceFilter * iface, LPCOLESTR pszFi This->pmt->pUnk = NULL; This->pmt->lSampleSize = 0; This->pmt->formattype = FORMAT_None; - hr = GetClassMediaFile(pReader, pszFileName, &This->pmt->majortype, &This->pmt->subtype); + hr = GetClassMediaFile(pReader, pszFileName, &This->pmt->majortype, &This->pmt->subtype, NULL); if (FAILED(hr)) { CoTaskMemFree(This->pmt); @@ -759,9 +732,10 @@ typedef struct DATAREQUEST typedef struct FileAsyncReader { - OutputPin pin; - const struct IAsyncReaderVtbl * lpVtblAR; + BaseOutputPin pin; + IAsyncReader IAsyncReader_iface; + ALLOCATOR_PROPERTIES allocProps; HANDLE hFile; BOOL bFlushing; /* Why would you need more? Every sample has its own handle */ @@ -775,30 +749,62 @@ typedef struct FileAsyncReader HANDLE *handle_list; } FileAsyncReader; -static inline FileAsyncReader *impl_from_IAsyncReader( IAsyncReader *iface ) +static inline FileAsyncReader *impl_from_IPin(IPin *iface) { - return (FileAsyncReader *)((char*)iface - FIELD_OFFSET(FileAsyncReader, lpVtblAR)); + return CONTAINING_RECORD(iface, FileAsyncReader, pin.pin.IPin_iface); } -static HRESULT AcceptProcAFR(LPVOID iface, const AM_MEDIA_TYPE *pmt) +static inline FileAsyncReader *impl_from_BasePin(BasePin *iface) { - AsyncReader *This = iface; + return CONTAINING_RECORD(iface, FileAsyncReader, pin.pin); +} + +static inline FileAsyncReader *impl_from_BaseOutputPin(BaseOutputPin *iface) +{ + return CONTAINING_RECORD(iface, FileAsyncReader, pin); +} + +static inline BaseOutputPin *impl_BaseOututPin_from_BasePin(BasePin *iface) +{ + return CONTAINING_RECORD(iface, BaseOutputPin, pin); +} + +static inline FileAsyncReader *impl_from_IAsyncReader(IAsyncReader *iface) +{ + return CONTAINING_RECORD(iface, FileAsyncReader, IAsyncReader_iface); +} + +static HRESULT WINAPI FileAsyncReaderPin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *pmt) +{ + FileAsyncReader *This = impl_from_IPin(iface); + AM_MEDIA_TYPE *pmt_filter = impl_from_IBaseFilter(This->pin.pin.pinInfo.pFilter)->pmt; FIXME("(%p, %p)\n", iface, pmt); - if (IsEqualGUID(&pmt->majortype, &This->pmt->majortype) && - IsEqualGUID(&pmt->subtype, &This->pmt->subtype) && + if (IsEqualGUID(&pmt->majortype, &pmt_filter->majortype) && + IsEqualGUID(&pmt->subtype, &pmt_filter->subtype) && IsEqualGUID(&pmt->formattype, &FORMAT_None)) return S_OK; - + return S_FALSE; } +static HRESULT WINAPI FileAsyncReaderPin_GetMediaType(BasePin *iface, int iPosition, AM_MEDIA_TYPE *pmt) +{ + FileAsyncReader *This = impl_from_BasePin(iface); + if (iPosition < 0) + return E_INVALIDARG; + if (iPosition > 0) + return VFW_S_NO_MORE_ITEMS; + CopyMediaType(pmt, impl_from_IBaseFilter(This->pin.pin.pinInfo.pFilter)->pmt); + return S_OK; +} + /* overridden pin functions */ static HRESULT WINAPI FileAsyncReaderPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv) { - FileAsyncReader *This = (FileAsyncReader *)iface; + FileAsyncReader *This = impl_from_IPin(iface); TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv); *ppv = NULL; @@ -808,7 +814,7 @@ static HRESULT WINAPI FileAsyncReaderPin_QueryInterface(IPin * iface, REFIID rii else if (IsEqualIID(riid, &IID_IPin)) *ppv = This; else if (IsEqualIID(riid, &IID_IAsyncReader)) - *ppv = &This->lpVtblAR; + *ppv = &This->IAsyncReader_iface; if (*ppv) { @@ -824,7 +830,7 @@ static HRESULT WINAPI FileAsyncReaderPin_QueryInterface(IPin * iface, REFIID rii static ULONG WINAPI FileAsyncReaderPin_Release(IPin * iface) { - FileAsyncReader *This = (FileAsyncReader *)iface; + FileAsyncReader *This = impl_from_IPin(iface); ULONG refCount = InterlockedDecrement(&This->pin.pin.refCount); int x; @@ -848,48 +854,35 @@ static ULONG WINAPI FileAsyncReaderPin_Release(IPin * iface) return refCount; } -static HRESULT WINAPI FileAsyncReaderPin_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum) -{ - ENUMMEDIADETAILS emd; - FileAsyncReader *This = (FileAsyncReader *)iface; - - TRACE("(%p)\n", ppEnum); - - emd.cMediaTypes = 1; - emd.pMediaTypes = ((AsyncReader *)This->pin.pin.pinInfo.pFilter)->pmt; - - return IEnumMediaTypesImpl_Construct(&emd, ppEnum); -} - static const IPinVtbl FileAsyncReaderPin_Vtbl = { FileAsyncReaderPin_QueryInterface, - IPinImpl_AddRef, + BasePinImpl_AddRef, FileAsyncReaderPin_Release, - OutputPin_Connect, - OutputPin_ReceiveConnection, - IPinImpl_Disconnect, - IPinImpl_ConnectedTo, - IPinImpl_ConnectionMediaType, - IPinImpl_QueryPinInfo, - IPinImpl_QueryDirection, - IPinImpl_QueryId, - IPinImpl_QueryAccept, - FileAsyncReaderPin_EnumMediaTypes, - IPinImpl_QueryInternalConnections, - OutputPin_EndOfStream, - OutputPin_BeginFlush, - OutputPin_EndFlush, - OutputPin_NewSegment + BaseOutputPinImpl_Connect, + BaseOutputPinImpl_ReceiveConnection, + BasePinImpl_Disconnect, + BasePinImpl_ConnectedTo, + BasePinImpl_ConnectionMediaType, + BasePinImpl_QueryPinInfo, + BasePinImpl_QueryDirection, + BasePinImpl_QueryId, + FileAsyncReaderPin_QueryAccept, + BasePinImpl_EnumMediaTypes, + BasePinImpl_QueryInternalConnections, + BaseOutputPinImpl_EndOfStream, + BaseOutputPinImpl_BeginFlush, + BaseOutputPinImpl_EndFlush, + BasePinImpl_NewSegment }; /* Function called as a helper to IPin_Connect */ /* specific AM_MEDIA_TYPE - it cannot be NULL */ -/* this differs from standard OutputPin_ConnectSpecific only in that it +/* this differs from standard OutputPin_AttemptConnection only in that it * doesn't need the IMemInputPin interface on the receiving pin */ -static HRESULT FileAsyncReaderPin_ConnectSpecific(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) +static HRESULT WINAPI FileAsyncReaderPin_AttemptConnection(BasePin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) { - OutputPin *This = (OutputPin *)iface; + BaseOutputPin *This = impl_BaseOututPin_from_BasePin(iface); HRESULT hr; TRACE("(%p, %p)\n", pReceivePin, pmt); @@ -901,7 +894,7 @@ static HRESULT FileAsyncReaderPin_ConnectSpecific(IPin * iface, IPin * pReceiveP IPin_AddRef(pReceivePin); CopyMediaType(&This->pin.mtCurrent, pmt); - hr = IPin_ReceiveConnection(pReceivePin, iface, pmt); + hr = IPin_ReceiveConnection(pReceivePin, &iface->IPin_iface, pmt); if (FAILED(hr)) { @@ -914,6 +907,36 @@ static HRESULT FileAsyncReaderPin_ConnectSpecific(IPin * iface, IPin * pReceiveP return hr; } +static HRESULT WINAPI FileAsyncReaderPin_DecideBufferSize(BaseOutputPin *iface, IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest) +{ + FileAsyncReader *This = impl_from_BaseOutputPin(iface); + ALLOCATOR_PROPERTIES actual; + + if (ppropInputRequest->cbAlign && ppropInputRequest->cbAlign != This->allocProps.cbAlign) + FIXME("Requested Buffer cbAlign mismatch %i,%i\n",This->allocProps.cbAlign, ppropInputRequest->cbAlign); + if (ppropInputRequest->cbPrefix) + FIXME("Requested Buffer cbPrefix mismatch %i,%i\n",This->allocProps.cbPrefix, ppropInputRequest->cbPrefix); + if (ppropInputRequest->cbBuffer) + FIXME("Requested Buffer cbBuffer mismatch %i,%i\n",This->allocProps.cbBuffer, ppropInputRequest->cbBuffer); + if (ppropInputRequest->cBuffers) + FIXME("Requested Buffer cBuffers mismatch %i,%i\n",This->allocProps.cBuffers, ppropInputRequest->cBuffers); + + return IMemAllocator_SetProperties(pAlloc, &This->allocProps, &actual); +} + +static const BasePinFuncTable output_BaseFuncTable = { + NULL, + FileAsyncReaderPin_AttemptConnection, + BasePinImpl_GetMediaTypeVersion, + FileAsyncReaderPin_GetMediaType +}; + +static const BaseOutputPinFuncTable output_BaseOutputFuncTable = { + FileAsyncReaderPin_DecideBufferSize, + BaseOutputPinImpl_DecideAllocator, + BaseOutputPinImpl_BreakConnect +}; + static HRESULT FileAsyncReader_Construct(HANDLE hFile, IBaseFilter * pBaseFilter, LPCRITICAL_SECTION pCritSec, IPin ** ppPin) { PIN_INFO piOutput; @@ -923,18 +946,17 @@ static HRESULT FileAsyncReader_Construct(HANDLE hFile, IBaseFilter * pBaseFilter piOutput.dir = PINDIR_OUTPUT; piOutput.pFilter = pBaseFilter; strcpyW(piOutput.achName, wszOutputPinName); - hr = OutputPin_Construct(&FileAsyncReaderPin_Vtbl, sizeof(FileAsyncReader), &piOutput, NULL, pBaseFilter, AcceptProcAFR, pCritSec, ppPin); + hr = BaseOutputPin_Construct(&FileAsyncReaderPin_Vtbl, sizeof(FileAsyncReader), &piOutput, &output_BaseFuncTable, &output_BaseOutputFuncTable, pCritSec, ppPin); if (SUCCEEDED(hr)) { FileAsyncReader *pPinImpl = (FileAsyncReader *)*ppPin; - pPinImpl->lpVtblAR = &FileAsyncReader_Vtbl; + pPinImpl->IAsyncReader_iface.lpVtbl = &FileAsyncReader_Vtbl; pPinImpl->hFile = hFile; pPinImpl->bFlushing = FALSE; pPinImpl->sample_list = NULL; pPinImpl->handle_list = NULL; pPinImpl->queued_number = 0; - pPinImpl->pin.pConnectSpecific = FileAsyncReaderPin_ConnectSpecific; InitializeCriticalSection(&pPinImpl->csList); pPinImpl->csList.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": FileAsyncReader.csList"); } @@ -947,21 +969,21 @@ static HRESULT WINAPI FileAsyncReader_QueryInterface(IAsyncReader * iface, REFII { FileAsyncReader *This = impl_from_IAsyncReader(iface); - return IPin_QueryInterface((IPin *)This, riid, ppv); + return IPin_QueryInterface(&This->pin.pin.IPin_iface, riid, ppv); } static ULONG WINAPI FileAsyncReader_AddRef(IAsyncReader * iface) { FileAsyncReader *This = impl_from_IAsyncReader(iface); - return IPin_AddRef((IPin *)This); + return IPin_AddRef(&This->pin.pin.IPin_iface); } static ULONG WINAPI FileAsyncReader_Release(IAsyncReader * iface) { FileAsyncReader *This = impl_from_IAsyncReader(iface); - return IPin_Release((IPin *)This); + return IPin_Release(&This->pin.pin.IPin_iface); } #define DEF_ALIGNMENT 1 @@ -1034,7 +1056,7 @@ done: This->handle_list[This->samples + 1 + x] = This->handle_list[x]; } This->handle_list[This->samples] = CreateEventW(NULL, 1, 0, NULL); - This->pin.allocProps = *pProps; + This->allocProps = *pProps; } else { @@ -1113,8 +1135,8 @@ static HRESULT WINAPI FileAsyncReader_Request(IAsyncReader * iface, IMediaSample pDataRq = This->sample_list + x; - pDataRq->ovl.Offset = (DWORD) BYTES_FROM_MEDIATIME(Start); - pDataRq->ovl.OffsetHigh = (DWORD)(BYTES_FROM_MEDIATIME(Start) >> (sizeof(DWORD) * 8)); + pDataRq->ovl.u.s.Offset = (DWORD) BYTES_FROM_MEDIATIME(Start); + pDataRq->ovl.u.s.OffsetHigh = (DWORD)(BYTES_FROM_MEDIATIME(Start) >> (sizeof(DWORD) * 8)); pDataRq->dwUserData = dwUser; /* we violate traditional COM rules here by maintaining @@ -1239,7 +1261,7 @@ static HRESULT WINAPI FileAsyncReader_WaitForNext(IAsyncReader * iface, DWORD dw /* Set the time on the sample */ IMediaSample_SetActualDataLength(pDataRq->pSample, dwBytes); - rtStart = (DWORD64)pDataRq->ovl.Offset + ((DWORD64)pDataRq->ovl.OffsetHigh << 32); + rtStart = (DWORD64)pDataRq->ovl.u.s.Offset + ((DWORD64)pDataRq->ovl.u.s.OffsetHigh << 32); rtStart = MEDIATIME_FROM_BYTES(rtStart); rtStop = rtStart + MEDIATIME_FROM_BYTES(dwBytes); @@ -1317,8 +1339,8 @@ static HRESULT WINAPI FileAsyncReader_SyncRead(IAsyncReader * iface, LONGLONG ll ovl.hEvent = CreateEventW(NULL, 0, 0, NULL); /* NOTE: llPosition is the actual byte position to start reading from */ - ovl.Offset = (DWORD) llPosition; - ovl.OffsetHigh = (DWORD) (llPosition >> (sizeof(DWORD) * 8)); + ovl.u.s.Offset = (DWORD) llPosition; + ovl.u.s.OffsetHigh = (DWORD) (llPosition >> (sizeof(DWORD) * 8)); if (!ReadFile(This->hFile, pBuffer, lLength, NULL, &ovl)) hr = HRESULT_FROM_WIN32(GetLastError()); @@ -1406,3 +1428,30 @@ static const IAsyncReaderVtbl FileAsyncReader_Vtbl = FileAsyncReader_BeginFlush, FileAsyncReader_EndFlush, }; + + +static HRESULT WINAPI AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid, void **ppv) { + AsyncReader *This = impl_from_IAMFilterMiscFlags(iface); + return IUnknown_QueryInterface((IUnknown*)This, riid, ppv); +} + +static ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface) { + AsyncReader *This = impl_from_IAMFilterMiscFlags(iface); + return IUnknown_AddRef((IUnknown*)This); +} + +static ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface) { + AsyncReader *This = impl_from_IAMFilterMiscFlags(iface); + return IUnknown_Release((IUnknown*)This); +} + +static ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface) { + return AM_FILTER_MISC_FLAGS_IS_SOURCE; +} + +static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = { + AMFilterMiscFlags_QueryInterface, + AMFilterMiscFlags_AddRef, + AMFilterMiscFlags_Release, + AMFilterMiscFlags_GetMiscFlags +}; diff --git a/reactos/dll/directx/quartz/filtergraph.c b/reactos/dll/directx/quartz/filtergraph.c index 553e026ab65..896762f538f 100644 --- a/reactos/dll/directx/quartz/filtergraph.c +++ b/reactos/dll/directx/quartz/filtergraph.c @@ -3,9 +3,6 @@ * Copyright 2002 Lionel Ulmer * Copyright 2004 Christian Costa * - * This file contains the (internal) driver registration functions, - * driver enumeration APIs and DirectDraw creation functions. - * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -22,23 +19,23 @@ */ #include -//#include +#include #define COBJMACROS -//#include "windef.h" -//#include "winbase.h" -//#include "winuser.h" -//#include "winreg.h" -//#include "dshow.h" +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "winreg.h" +#include "shlwapi.h" +#include "dshow.h" #include #include "quartz_private.h" -#include -//#include "ole2.h" -//#include "olectl.h" -//#include "strmif.h" -//#include "vfwmsgs.h" -//#include "evcode.h" +#include "ole2.h" +#include "olectl.h" +#include +#include "vfwmsgs.h" +#include "evcode.h" #include @@ -94,12 +91,12 @@ static int EventsQueue_Destroy(EventsQueue* omr) static int EventsQueue_PutEvent(EventsQueue* omr, const Event* evt) { EnterCriticalSection(&omr->msg_crst); - if ((omr->msg_toget == ((omr->msg_tosave + 1) % omr->ring_buffer_size))) + if (omr->msg_toget == ((omr->msg_tosave + 1) % omr->ring_buffer_size)) { int old_ring_buffer_size = omr->ring_buffer_size; omr->ring_buffer_size += EVENTS_RING_BUFFER_INCREMENT; TRACE("omr->ring_buffer_size=%d\n",omr->ring_buffer_size); - omr->messages = HeapReAlloc(GetProcessHeap(),0,omr->messages, omr->ring_buffer_size * sizeof(Event)); + omr->messages = CoTaskMemRealloc(omr->messages, omr->ring_buffer_size * sizeof(Event)); /* Now we need to rearrange the ring buffer so that the new buffers just allocated are in between omr->msg_tosave and omr->msg_toget. @@ -152,38 +149,41 @@ typedef struct _ITF_CACHE_ENTRY { } ITF_CACHE_ENTRY; typedef struct _IFilterGraphImpl { - const IFilterGraph2Vtbl *IFilterGraph2_vtbl; - const IMediaControlVtbl *IMediaControl_vtbl; - const IMediaSeekingVtbl *IMediaSeeking_vtbl; - const IBasicAudioVtbl *IBasicAudio_vtbl; - const IBasicVideo2Vtbl *IBasicVideo_vtbl; - const IVideoWindowVtbl *IVideoWindow_vtbl; - const IMediaEventExVtbl *IMediaEventEx_vtbl; - const IMediaFilterVtbl *IMediaFilter_vtbl; - const IMediaEventSinkVtbl *IMediaEventSink_vtbl; - const IGraphConfigVtbl *IGraphConfig_vtbl; - const IMediaPositionVtbl *IMediaPosition_vtbl; - const IUnknownVtbl * IInner_vtbl; + IUnknown IUnknown_inner; + IFilterGraph2 IFilterGraph2_iface; + IMediaControl IMediaControl_iface; + IMediaSeeking IMediaSeeking_iface; + IBasicAudio IBasicAudio_iface; + IBasicVideo2 IBasicVideo2_iface; + IVideoWindow IVideoWindow_iface; + IMediaEventEx IMediaEventEx_iface; + IMediaFilter IMediaFilter_iface; + IMediaEventSink IMediaEventSink_iface; + IGraphConfig IGraphConfig_iface; + IMediaPosition IMediaPosition_iface; + IObjectWithSite IObjectWithSite_iface; + IGraphVersion IGraphVersion_iface; /* IAMGraphStreams */ /* IAMStats */ /* IFilterChain */ /* IFilterMapper2 */ - /* IGraphVersion */ /* IQueueCommand */ /* IRegisterServiceProvider */ /* IResourceMananger */ /* IServiceProvider */ /* IVideoFrameStep */ + IUnknown *outer_unk; LONG ref; IUnknown *punkFilterMapper2; IFilterMapper2 * pFilterMapper2; IBaseFilter ** ppFiltersInGraph; LPWSTR * pFilterNames; - int nFilters; + ULONG nFilters; int filterCapacity; LONG nameIndex; IReferenceClock *refClock; + IBaseFilter *refClockProvider; EventsQueue evqueue; HANDLE hEventCompletion; int CompletionStatus; @@ -197,99 +197,105 @@ typedef struct _IFilterGraphImpl { CRITICAL_SECTION cs; ITF_CACHE_ENTRY ItfCacheEntries[MAX_ITF_CACHE_ENTRIES]; int nItfCacheEntries; - IUnknown * pUnkOuter; - BOOL bUnkOuterValid; - BOOL bAggregatable; + BOOL defaultclock; GUID timeformatseek; - LONGLONG start_time; - LONGLONG position; + REFERENCE_TIME start_time; + REFERENCE_TIME pause_time; LONGLONG stop_position; LONG recursioncount; + IUnknown *pSite; + LONG version; } IFilterGraphImpl; -static HRESULT Filtergraph_QueryInterface(IFilterGraphImpl *This, - REFIID riid, LPVOID * ppv); -static ULONG Filtergraph_AddRef(IFilterGraphImpl *This); -static ULONG Filtergraph_Release(IFilterGraphImpl *This); +static inline IFilterGraphImpl *impl_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, IFilterGraphImpl, IUnknown_inner); +} -static HRESULT WINAPI FilterGraphInner_QueryInterface(IUnknown * iface, - REFIID riid, - LPVOID *ppvObj) { - ICOM_THIS_MULTI(IFilterGraphImpl, IInner_vtbl, iface); +static HRESULT WINAPI FilterGraphInner_QueryInterface(IUnknown *iface, REFIID riid, void **ppvObj) +{ + IFilterGraphImpl *This = impl_from_IUnknown(iface); TRACE("(%p)->(%s (%p), %p)\n", This, debugstr_guid(riid), riid, ppvObj); - - if (This->bAggregatable) - This->bUnkOuterValid = TRUE; if (IsEqualGUID(&IID_IUnknown, riid)) { - *ppvObj = &(This->IInner_vtbl); + *ppvObj = &This->IUnknown_inner; TRACE(" returning IUnknown interface (%p)\n", *ppvObj); } else if (IsEqualGUID(&IID_IFilterGraph, riid) || IsEqualGUID(&IID_IFilterGraph2, riid) || IsEqualGUID(&IID_IGraphBuilder, riid)) { - *ppvObj = &(This->IFilterGraph2_vtbl); + *ppvObj = &This->IFilterGraph2_iface; TRACE(" returning IGraphBuilder interface (%p)\n", *ppvObj); } else if (IsEqualGUID(&IID_IMediaControl, riid)) { - *ppvObj = &(This->IMediaControl_vtbl); + *ppvObj = &This->IMediaControl_iface; TRACE(" returning IMediaControl interface (%p)\n", *ppvObj); } else if (IsEqualGUID(&IID_IMediaSeeking, riid)) { - *ppvObj = &(This->IMediaSeeking_vtbl); + *ppvObj = &This->IMediaSeeking_iface; TRACE(" returning IMediaSeeking interface (%p)\n", *ppvObj); } else if (IsEqualGUID(&IID_IBasicAudio, riid)) { - *ppvObj = &(This->IBasicAudio_vtbl); + *ppvObj = &This->IBasicAudio_iface; TRACE(" returning IBasicAudio interface (%p)\n", *ppvObj); } else if (IsEqualGUID(&IID_IBasicVideo, riid) || IsEqualGUID(&IID_IBasicVideo2, riid)) { - *ppvObj = &(This->IBasicVideo_vtbl); + *ppvObj = &This->IBasicVideo2_iface; TRACE(" returning IBasicVideo2 interface (%p)\n", *ppvObj); } else if (IsEqualGUID(&IID_IVideoWindow, riid)) { - *ppvObj = &(This->IVideoWindow_vtbl); + *ppvObj = &This->IVideoWindow_iface; TRACE(" returning IVideoWindow interface (%p)\n", *ppvObj); } else if (IsEqualGUID(&IID_IMediaEvent, riid) || IsEqualGUID(&IID_IMediaEventEx, riid)) { - *ppvObj = &(This->IMediaEventEx_vtbl); + *ppvObj = &This->IMediaEventEx_iface; TRACE(" returning IMediaEvent(Ex) interface (%p)\n", *ppvObj); } else if (IsEqualGUID(&IID_IMediaFilter, riid) || IsEqualGUID(&IID_IPersist, riid)) { - *ppvObj = &(This->IMediaFilter_vtbl); + *ppvObj = &This->IMediaFilter_iface; TRACE(" returning IMediaFilter interface (%p)\n", *ppvObj); } else if (IsEqualGUID(&IID_IMediaEventSink, riid)) { - *ppvObj = &(This->IMediaEventSink_vtbl); + *ppvObj = &This->IMediaEventSink_iface; TRACE(" returning IMediaEventSink interface (%p)\n", *ppvObj); } else if (IsEqualGUID(&IID_IGraphConfig, riid)) { - *ppvObj = &(This->IGraphConfig_vtbl); + *ppvObj = &This->IGraphConfig_iface; TRACE(" returning IGraphConfig interface (%p)\n", *ppvObj); } else if (IsEqualGUID(&IID_IMediaPosition, riid)) { - *ppvObj = &(This->IMediaPosition_vtbl); + *ppvObj = &This->IMediaPosition_iface; TRACE(" returning IMediaPosition interface (%p)\n", *ppvObj); + } else if (IsEqualGUID(&IID_IObjectWithSite, riid)) { + *ppvObj = &This->IObjectWithSite_iface; + TRACE(" returning IObjectWithSite interface (%p)\n", *ppvObj); } else if (IsEqualGUID(&IID_IFilterMapper, riid)) { TRACE(" requesting IFilterMapper interface from aggregated filtermapper (%p)\n", *ppvObj); return IUnknown_QueryInterface(This->punkFilterMapper2, riid, ppvObj); } else if (IsEqualGUID(&IID_IFilterMapper2, riid)) { *ppvObj = This->pFilterMapper2; TRACE(" returning IFilterMapper2 interface from aggregated filtermapper (%p)\n", *ppvObj); + } else if (IsEqualGUID(&IID_IFilterMapper3, riid)) { + *ppvObj = This->pFilterMapper2; + TRACE(" returning IFilterMapper3 interface from aggregated filtermapper (%p)\n", *ppvObj); + } else if (IsEqualGUID(&IID_IGraphVersion, riid)) { + *ppvObj = &This->IGraphConfig_iface; + TRACE(" returning IGraphConfig interface (%p)\n", *ppvObj); } else { *ppvObj = NULL; FIXME("unknown interface %s\n", debugstr_guid(riid)); return E_NOINTERFACE; } - IUnknown_AddRef((IUnknown *)(*ppvObj)); + IUnknown_AddRef((IUnknown *)*ppvObj); return S_OK; } -static ULONG WINAPI FilterGraphInner_AddRef(IUnknown * iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IInner_vtbl, iface); +static ULONG WINAPI FilterGraphInner_AddRef(IUnknown *iface) +{ + IFilterGraphImpl *This = impl_from_IUnknown(iface); ULONG ref = InterlockedIncrement(&This->ref); TRACE("(%p)->(): new ref = %d\n", This, ref); - + return ref; } -static ULONG WINAPI FilterGraphInner_Release(IUnknown * iface) +static ULONG WINAPI FilterGraphInner_Release(IUnknown *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IInner_vtbl, iface); + IFilterGraphImpl *This = impl_from_IUnknown(iface); ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p)->(): new ref = %d\n", This, ref); @@ -299,10 +305,10 @@ static ULONG WINAPI FilterGraphInner_Release(IUnknown * iface) This->ref = 1; /* guard against reentrancy (aggregation). */ - IMediaControl_Stop((IMediaControl*)&(This->IMediaControl_vtbl)); + IMediaControl_Stop(&This->IMediaControl_iface); while (This->nFilters) - IFilterGraph2_RemoveFilter((IFilterGraph2*)This, This->ppFiltersInGraph[0]); + IFilterGraph2_RemoveFilter(&This->IFilterGraph2_iface, This->ppFiltersInGraph[0]); if (This->refClock) IReferenceClock_Release(This->refClock); @@ -313,18 +319,13 @@ static ULONG WINAPI FilterGraphInner_Release(IUnknown * iface) IUnknown_Release(This->ItfCacheEntries[i].iface); } - /* AddRef on controlling IUnknown, to compensate for Release of cached IFilterMapper2 interface below. - - * NOTE: Filtergraph_AddRef isn't suitable, because bUnkOuterValid may be FALSE but punkOuter non-NULL - * and already passed as punkOuter to filtermapper in FilterGraph_create - this will happen in case of - * CoCreateInstance of filtergraph with non-null pUnkOuter and REFIID other than IID_Unknown that is - * cleaning up after error. */ - if (This->pUnkOuter) IUnknown_AddRef(This->pUnkOuter); - else IUnknown_AddRef((IUnknown*)&This->IInner_vtbl); - + /* AddRef on controlling IUnknown, to compensate for Release of cached IFilterMapper2 */ + IUnknown_AddRef(This->outer_unk); IFilterMapper2_Release(This->pFilterMapper2); IUnknown_Release(This->punkFilterMapper2); + if (This->pSite) IUnknown_Release(This->pSite); + CloseHandle(This->hEventCompletion); EventsQueue_Destroy(&This->evqueue); This->cs.DebugInfo->Spare[0] = 0; @@ -336,38 +337,43 @@ static ULONG WINAPI FilterGraphInner_Release(IUnknown * iface) return ref; } +static inline IFilterGraphImpl *impl_from_IFilterGraph2(IFilterGraph2 *iface) +{ + return CONTAINING_RECORD(iface, IFilterGraphImpl, IFilterGraph2_iface); +} + +static HRESULT WINAPI FilterGraph2_QueryInterface(IFilterGraph2 *iface, REFIID riid, void **ppvObj) +{ + IFilterGraphImpl *This = impl_from_IFilterGraph2(iface); -/*** IUnknown methods ***/ -static HRESULT WINAPI FilterGraph2_QueryInterface(IFilterGraph2 *iface, - REFIID riid, - LPVOID*ppvObj) { - ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); - TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); - return Filtergraph_QueryInterface(This, riid, ppvObj); + + return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj); } -static ULONG WINAPI FilterGraph2_AddRef(IFilterGraph2 *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); - - TRACE("(%p/%p)->() calling FilterGraph AddRef\n", This, iface); - - return Filtergraph_AddRef(This); +static ULONG WINAPI FilterGraph2_AddRef(IFilterGraph2 *iface) +{ + IFilterGraphImpl *This = impl_from_IFilterGraph2(iface); + + TRACE("(%p/%p)->()\n", This, iface); + + return IUnknown_AddRef(This->outer_unk); } -static ULONG WINAPI FilterGraph2_Release(IFilterGraph2 *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); - - TRACE("(%p/%p)->() calling FilterGraph Release\n", This, iface); +static ULONG WINAPI FilterGraph2_Release(IFilterGraph2 *iface) +{ + IFilterGraphImpl *This = impl_from_IFilterGraph2(iface); - return Filtergraph_Release(This); + TRACE("(%p/%p)->()\n", This, iface); + + return IUnknown_Release(This->outer_unk); } /*** IFilterGraph methods ***/ -static HRESULT WINAPI FilterGraph2_AddFilter(IFilterGraph2 *iface, - IBaseFilter *pFilter, - LPCWSTR pName) { - ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); +static HRESULT WINAPI FilterGraph2_AddFilter(IFilterGraph2 *iface, IBaseFilter *pFilter, + LPCWSTR pName) +{ + IFilterGraphImpl *This = impl_from_IFilterGraph2(iface); HRESULT hr; int i,j; WCHAR* wszFilterName = NULL; @@ -452,20 +458,21 @@ static HRESULT WINAPI FilterGraph2_AddFilter(IFilterGraph2 *iface, This->ppFiltersInGraph[This->nFilters] = pFilter; This->pFilterNames[This->nFilters] = wszFilterName; This->nFilters++; + This->version++; IBaseFilter_SetSyncSource(pFilter, This->refClock); } else - CoTaskMemFree(wszFilterName); + CoTaskMemFree(wszFilterName); if (SUCCEEDED(hr) && duplicate_name) - return VFW_S_DUPLICATE_NAME; - + return VFW_S_DUPLICATE_NAME; + return hr; } static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, IBaseFilter *pFilter) { - ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); + IFilterGraphImpl *This = impl_from_IFilterGraph2(iface); int i; HRESULT hr = E_FAIL; @@ -480,6 +487,12 @@ static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, IBaseFilte IEnumPins *penumpins = NULL; FILTER_STATE state; + if (This->defaultclock && This->refClockProvider == pFilter) + { + IMediaFilter_SetSyncSource(&This->IMediaFilter_iface, NULL); + This->defaultclock = 1; + } + TRACE("Removing filter %s\n", debugstr_w(This->pFilterNames[i])); IBaseFilter_GetState(pFilter, 0, &state); if (state == State_Running) @@ -531,6 +544,7 @@ static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, IBaseFilte memmove(This->ppFiltersInGraph+i, This->ppFiltersInGraph+i+1, sizeof(IBaseFilter*)*(This->nFilters - 1 - i)); memmove(This->pFilterNames+i, This->pFilterNames+i+1, sizeof(LPWSTR)*(This->nFilters - 1 - i)); This->nFilters--; + This->version++; /* Invalidate interfaces in the cache */ for (i = 0; i < This->nItfCacheEntries; i++) if (pFilter == This->ItfCacheEntries[i].filter) @@ -548,19 +562,19 @@ static HRESULT WINAPI FilterGraph2_RemoveFilter(IFilterGraph2 *iface, IBaseFilte return hr; /* FIXME: check this error code */ } -static HRESULT WINAPI FilterGraph2_EnumFilters(IFilterGraph2 *iface, - IEnumFilters **ppEnum) { - ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); +static HRESULT WINAPI FilterGraph2_EnumFilters(IFilterGraph2 *iface, IEnumFilters **ppEnum) +{ + IFilterGraphImpl *This = impl_from_IFilterGraph2(iface); TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum); - return IEnumFiltersImpl_Construct(This->ppFiltersInGraph, This->nFilters, ppEnum); + return IEnumFiltersImpl_Construct(&This->IGraphVersion_iface, &This->ppFiltersInGraph, &This->nFilters, ppEnum); } -static HRESULT WINAPI FilterGraph2_FindFilterByName(IFilterGraph2 *iface, - LPCWSTR pName, - IBaseFilter **ppFilter) { - ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); +static HRESULT WINAPI FilterGraph2_FindFilterByName(IFilterGraph2 *iface, LPCWSTR pName, + IBaseFilter **ppFilter) +{ + IFilterGraphImpl *This = impl_from_IFilterGraph2(iface); int i; TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_w(pName), pName, ppFilter); @@ -661,15 +675,13 @@ out: /* NOTE: despite the implication, it doesn't matter which * way round you put in the input and output pins */ -static HRESULT WINAPI FilterGraph2_ConnectDirect(IFilterGraph2 *iface, - IPin *ppinIn, - IPin *ppinOut, - const AM_MEDIA_TYPE *pmt) { +static HRESULT WINAPI FilterGraph2_ConnectDirect(IFilterGraph2 *iface, IPin *ppinIn, IPin *ppinOut, + const AM_MEDIA_TYPE *pmt) +{ + IFilterGraphImpl *This = impl_from_IFilterGraph2(iface); PIN_DIRECTION dir; HRESULT hr; - ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); - TRACE("(%p/%p)->(%p, %p, %p)\n", This, iface, ppinIn, ppinOut, pmt); /* FIXME: check pins are in graph */ @@ -713,9 +725,9 @@ static HRESULT WINAPI FilterGraph2_ConnectDirect(IFilterGraph2 *iface, return hr; } -static HRESULT WINAPI FilterGraph2_Reconnect(IFilterGraph2 *iface, - IPin *ppin) { - ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); +static HRESULT WINAPI FilterGraph2_Reconnect(IFilterGraph2 *iface, IPin *ppin) +{ + IFilterGraphImpl *This = impl_from_IFilterGraph2(iface); IPin *pConnectedTo = NULL; HRESULT hr; PIN_DIRECTION pindir; @@ -741,7 +753,7 @@ static HRESULT WINAPI FilterGraph2_Reconnect(IFilterGraph2 *iface, static HRESULT WINAPI FilterGraph2_Disconnect(IFilterGraph2 *iface, IPin *ppin) { - ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); + IFilterGraphImpl *This = impl_from_IFilterGraph2(iface); TRACE("(%p/%p)->(%p)\n", This, iface, ppin); @@ -751,27 +763,53 @@ static HRESULT WINAPI FilterGraph2_Disconnect(IFilterGraph2 *iface, IPin *ppin) return IPin_Disconnect(ppin); } -static HRESULT WINAPI FilterGraph2_SetDefaultSyncSource(IFilterGraph2 *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); +static HRESULT WINAPI FilterGraph2_SetDefaultSyncSource(IFilterGraph2 *iface) +{ + IFilterGraphImpl *This = impl_from_IFilterGraph2(iface); IReferenceClock *pClock = NULL; - HRESULT hr; + HRESULT hr = S_OK; + int i; - TRACE("(%p/%p)->() semi-stub\n", iface, This); + TRACE("(%p/%p)->() live sources not handled properly!\n", iface, This); - hr = CoCreateInstance(&CLSID_SystemClock, NULL, CLSCTX_INPROC_SERVER, &IID_IReferenceClock, (LPVOID*)&pClock); + EnterCriticalSection(&This->cs); + + for (i = 0; i < This->nFilters; ++i) + { + DWORD miscflags; + IAMFilterMiscFlags *flags = NULL; + IBaseFilter_QueryInterface(This->ppFiltersInGraph[i], &IID_IAMFilterMiscFlags, (void**)&flags); + if (!flags) + continue; + miscflags = IAMFilterMiscFlags_GetMiscFlags(flags); + IAMFilterMiscFlags_Release(flags); + if (miscflags == AM_FILTER_MISC_FLAGS_IS_RENDERER) + IBaseFilter_QueryInterface(This->ppFiltersInGraph[i], &IID_IReferenceClock, (void**)&pClock); + if (pClock) + break; + } + + if (!pClock) + { + hr = CoCreateInstance(&CLSID_SystemClock, NULL, CLSCTX_INPROC_SERVER, &IID_IReferenceClock, (LPVOID*)&pClock); + This->refClockProvider = NULL; + } + else + This->refClockProvider = This->ppFiltersInGraph[i]; if (SUCCEEDED(hr)) { - hr = IMediaFilter_SetSyncSource((IMediaFilter*)&(This->IMediaFilter_vtbl), pClock); + hr = IMediaFilter_SetSyncSource(&This->IMediaFilter_iface, pClock); + This->defaultclock = TRUE; IReferenceClock_Release(pClock); } + LeaveCriticalSection(&This->cs); return hr; } -static HRESULT GetFilterInfo(IMoniker* pMoniker, GUID* pclsid, VARIANT* pvar) +static HRESULT GetFilterInfo(IMoniker* pMoniker, VARIANT* pvar) { - static const WCHAR wszClsidName[] = {'C','L','S','I','D',0}; static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0}; IPropertyBag * pPropBagCat = NULL; HRESULT hr; @@ -780,19 +818,11 @@ static HRESULT GetFilterInfo(IMoniker* pMoniker, GUID* pclsid, VARIANT* pvar) hr = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID*)&pPropBagCat); - if (SUCCEEDED(hr)) - hr = IPropertyBag_Read(pPropBagCat, wszClsidName, pvar, NULL); - - if (SUCCEEDED(hr)) - hr = CLSIDFromString(V_UNION(pvar, bstrVal), pclsid); - - VariantClear(pvar); - if (SUCCEEDED(hr)) hr = IPropertyBag_Read(pPropBagCat, wszFriendlyName, pvar, NULL); if (SUCCEEDED(hr)) - TRACE("Moniker = %s - %s\n", debugstr_guid(pclsid), debugstr_w(V_UNION(pvar, bstrVal))); + TRACE("Moniker = %s\n", debugstr_w(V_UNION(pvar, bstrVal))); if (pPropBagCat) IPropertyBag_Release(pPropBagCat); @@ -865,7 +895,7 @@ static HRESULT GetInternalConnections(IBaseFilter* pfilter, IPin* pinputpin, IPi /*** IGraphBuilder methods ***/ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut, IPin *ppinIn) { - ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); + IFilterGraphImpl *This = impl_from_IFilterGraph2(iface); HRESULT hr; AM_MEDIA_TYPE* mt = NULL; IEnumMediaTypes* penummt = NULL; @@ -873,12 +903,13 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut, IEnumPins* penumpins; IEnumMoniker* pEnumMoniker; GUID tab[2]; - ULONG nb; + ULONG nb = 0; IMoniker* pMoniker; ULONG pin; PIN_INFO PinInfo; CLSID FilterCLSID; PIN_DIRECTION dir; + unsigned int i = 0; TRACE("(%p/%p)->(%p, %p)\n", This, iface, ppinOut, ppinIn); @@ -979,28 +1010,67 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut, { VARIANT var; GUID clsid; - IPin** ppins; + IPin** ppins = NULL; IPin* ppinfilter = NULL; IBaseFilter* pfilter = NULL; + IAMGraphBuilderCallback *callback = NULL; - hr = GetFilterInfo(pMoniker, &clsid, &var); - IMoniker_Release(pMoniker); + hr = GetFilterInfo(pMoniker, &var); if (FAILED(hr)) { WARN("Unable to retrieve filter info (%x)\n", hr); goto error; } - if (IsEqualGUID(&clsid, &FilterCLSID)) { - /* Skip filter (same as the one the output pin belongs to) */ - goto error; - } - - hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter); + hr = IMoniker_BindToObject(pMoniker, NULL, NULL, &IID_IBaseFilter, (LPVOID*)&pfilter); + IMoniker_Release(pMoniker); if (FAILED(hr)) { WARN("Unable to create filter (%x), trying next one\n", hr); goto error; } + hr = IBaseFilter_GetClassID(pfilter, &clsid); + if (FAILED(hr)) + { + IBaseFilter_Release(pfilter); + goto error; + } + + if (IsEqualGUID(&clsid, &FilterCLSID)) { + /* Skip filter (same as the one the output pin belongs to) */ + IBaseFilter_Release(pfilter); + goto error; + } + + if (This->pSite) + { + IUnknown_QueryInterface(This->pSite, &IID_IAMGraphBuilderCallback, (LPVOID*)&callback); + if (callback) + { + HRESULT rc; + rc = IAMGraphBuilderCallback_SelectedFilter(callback, pMoniker); + if (FAILED(rc)) + { + TRACE("Filter rejected by IAMGraphBuilderCallback_SelectedFilter\n"); + IAMGraphBuilderCallback_Release(callback); + goto error; + } + } + } + + if (callback) + { + HRESULT rc; + rc = IAMGraphBuilderCallback_CreatedFilter(callback, pfilter); + IAMGraphBuilderCallback_Release(callback); + if (FAILED(rc)) + { + IBaseFilter_Release(pfilter); + pfilter = NULL; + TRACE("Filter rejected by IAMGraphBuilderCallback_CreatedFilter\n"); + goto error; + } + } + hr = IFilterGraph2_AddFilter(iface, pfilter, V_UNION(&var, bstrVal)); if (FAILED(hr)) { WARN("Unable to add filter (%x)\n", hr); @@ -1040,7 +1110,6 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut, hr = GetInternalConnections(pfilter, ppinfilter, &ppins, &nb); if (SUCCEEDED(hr)) { - unsigned int i; if (nb == 0) { IPin_Disconnect(ppinfilter); IPin_Disconnect(ppinOut); @@ -1093,6 +1162,8 @@ error: IFilterGraph2_RemoveFilter(iface, pfilter); IBaseFilter_Release(pfilter); } + while (++i < nb) IPin_Release(ppins[i]); + CoTaskMemFree(ppins); } out: @@ -1136,7 +1207,7 @@ static HRESULT FilterGraph2_RenderRecurse(IFilterGraphImpl *This, IPin *ppinOut) if (!out) { HRESULT hr; - hr = IFilterGraph2_Render((IFilterGraph2 *)&This->IFilterGraph2_vtbl, to); + hr = IFilterGraph2_Render(&This->IFilterGraph2_iface, to); if (SUCCEEDED(hr)) renderany = TRUE; else @@ -1180,7 +1251,7 @@ static HRESULT FilterGraph2_RenderRecurse(IFilterGraphImpl *This, IPin *ppinOut) static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, IPin *ppinOut) { - ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); + IFilterGraphImpl *This = impl_from_IFilterGraph2(iface); IEnumMediaTypes* penummt; AM_MEDIA_TYPE* mt; ULONG nbmt; @@ -1235,7 +1306,7 @@ static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, IPin *ppinOut) if (to == NULL) { - hr = IPin_Connect(ppinOut, pin, NULL); + hr = FilterGraph2_ConnectDirect(iface, ppinOut, pin, NULL); if (SUCCEEDED(hr)) { TRACE("Connected successfully %p/%p, %08x look if we should render more!\n", ppinOut, pin, hr); @@ -1315,20 +1386,19 @@ static HRESULT WINAPI FilterGraph2_Render(IFilterGraph2 *iface, IPin *ppinOut) while (IEnumMoniker_Next(pEnumMoniker, 1, &pMoniker, &nb) == S_OK) { VARIANT var; - GUID clsid; IPin* ppinfilter; IBaseFilter* pfilter = NULL; IEnumPins* penumpins = NULL; ULONG pin; - hr = GetFilterInfo(pMoniker, &clsid, &var); - IMoniker_Release(pMoniker); + hr = GetFilterInfo(pMoniker, &var); if (FAILED(hr)) { WARN("Unable to retrieve filter info (%x)\n", hr); goto error; } - hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter); + hr = IMoniker_BindToObject(pMoniker, NULL, NULL, &IID_IBaseFilter, (LPVOID*)&pfilter); + IMoniker_Release(pMoniker); if (FAILED(hr)) { WARN("Unable to create filter (%x), trying next one\n", hr); @@ -1422,11 +1492,10 @@ error: return hr; } -static HRESULT WINAPI FilterGraph2_RenderFile(IFilterGraph2 *iface, - LPCWSTR lpcwstrFile, - LPCWSTR lpcwstrPlayList) +static HRESULT WINAPI FilterGraph2_RenderFile(IFilterGraph2 *iface, LPCWSTR lpcwstrFile, + LPCWSTR lpcwstrPlayList) { - ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); + IFilterGraphImpl *This = impl_from_IFilterGraph2(iface); static const WCHAR string[] = {'R','e','a','d','e','r',0}; IBaseFilter* preader = NULL; IPin* ppinreader = NULL; @@ -1485,68 +1554,103 @@ static HRESULT WINAPI FilterGraph2_RenderFile(IFilterGraph2 *iface, return hr; } -/* Some filters implement their own asynchronous reader (Theoretically they all should, try to load it first */ -static HRESULT GetFileSourceFilter(LPCOLESTR pszFileName, IBaseFilter **filter) +static HRESULT CreateFilterInstanceAndLoadFile(GUID* clsid, LPCOLESTR pszFileName, IBaseFilter **filter) { - static const WCHAR wszReg[] = {'M','e','d','i','a',' ','T','y','p','e','\\','E','x','t','e','n','s','i','o','n','s',0}; - HRESULT hr = S_OK; - HKEY extkey; - LONG lRet; - - lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszReg, 0, KEY_READ, &extkey); - hr = HRESULT_FROM_WIN32(lRet); - - if (SUCCEEDED(hr)) - { - static const WCHAR filtersource[] = {'S','o','u','r','c','e',' ','F','i','l','t','e','r',0}; - WCHAR *ext = PathFindExtensionW(pszFileName); - WCHAR clsid_key[39]; - GUID clsid; - DWORD size = sizeof(clsid_key); - HKEY pathkey; - - if (!ext) - { - CloseHandle(extkey); - return E_FAIL; - } - - lRet = RegOpenKeyExW(extkey, ext, 0, KEY_READ, &pathkey); - hr = HRESULT_FROM_WIN32(lRet); - CloseHandle(extkey); - if (FAILED(hr)) - return hr; - - lRet = RegQueryValueExW(pathkey, filtersource, NULL, NULL, (LPBYTE)clsid_key, &size); - hr = HRESULT_FROM_WIN32(lRet); - CloseHandle(pathkey); - if (FAILED(hr)) - return hr; - - CLSIDFromString(clsid_key, &clsid); - - TRACE("CLSID: %s\n", debugstr_guid(&clsid)); - hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)filter); - if (SUCCEEDED(hr)) - { - IFileSourceFilter *source = NULL; - hr = IBaseFilter_QueryInterface(*filter, &IID_IFileSourceFilter, (LPVOID*)&source); - if (SUCCEEDED(hr)) - IFileSourceFilter_Release(source); - else - IBaseFilter_Release(*filter); - } - } + IFileSourceFilter *source = NULL; + HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)filter); + TRACE("CLSID: %s\n", debugstr_guid(clsid)); if (FAILED(hr)) - *filter = NULL; + return hr; + + hr = IBaseFilter_QueryInterface(*filter, &IID_IFileSourceFilter, (LPVOID*)&source); + if (FAILED(hr)) + { + IBaseFilter_Release(*filter); + return hr; + } + + /* Load the file in the file source filter */ + hr = IFileSourceFilter_Load(source, pszFileName, NULL); + IFileSourceFilter_Release(source); + if (FAILED(hr)) { + WARN("Load (%x)\n", hr); + IBaseFilter_Release(*filter); + return hr; + } + return hr; } -static HRESULT WINAPI FilterGraph2_AddSourceFilter(IFilterGraph2 *iface, - LPCWSTR lpcwstrFileName, - LPCWSTR lpcwstrFilterName, - IBaseFilter **ppFilter) { - ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); +/* Some filters implement their own asynchronous reader (Theoretically they all should, try to load it first */ +static HRESULT GetFileSourceFilter(LPCOLESTR pszFileName, IBaseFilter **filter) +{ + HRESULT hr; + GUID clsid; + IAsyncReader * pReader = NULL; + IFileSourceFilter* pSource = NULL; + IPin * pOutputPin = NULL; + static const WCHAR wszOutputPinName[] = { 'O','u','t','p','u','t',0 }; + + /* Try to find a match without reading the file first */ + hr = GetClassMediaFile(NULL, pszFileName, NULL, NULL, &clsid); + + if (!hr) + return CreateFilterInstanceAndLoadFile(&clsid, pszFileName, filter); + + /* Now create a AyncReader instance, to check for signature bytes in the file */ + hr = CoCreateInstance(&CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)filter); + if (FAILED(hr)) + return hr; + + hr = IBaseFilter_QueryInterface(*filter, &IID_IFileSourceFilter, (LPVOID *)&pSource); + if (FAILED(hr)) + { + IBaseFilter_Release(*filter); + return hr; + } + + hr = IFileSourceFilter_Load(pSource, pszFileName, NULL); + IFileSourceFilter_Release(pSource); + if (FAILED(hr)) + { + IBaseFilter_Release(*filter); + return hr; + } + + hr = IBaseFilter_FindPin(*filter, wszOutputPinName, &pOutputPin); + if (FAILED(hr)) + { + IBaseFilter_Release(*filter); + return hr; + } + + hr = IPin_QueryInterface(pOutputPin, &IID_IAsyncReader, (LPVOID *)&pReader); + IPin_Release(pOutputPin); + if (FAILED(hr)) + { + IBaseFilter_Release(*filter); + return hr; + } + + /* Try again find a match */ + hr = GetClassMediaFile(pReader, pszFileName, NULL, NULL, &clsid); + IAsyncReader_Release(pReader); + + if (!hr) + { + /* Release the AsyncReader filter and create the matching one */ + IBaseFilter_Release(*filter); + return CreateFilterInstanceAndLoadFile(&clsid, pszFileName, filter); + } + + /* Return the AsyncReader filter */ + return S_OK; +} + +static HRESULT WINAPI FilterGraph2_AddSourceFilter(IFilterGraph2 *iface, LPCWSTR lpcwstrFileName, + LPCWSTR lpcwstrFilterName, IBaseFilter **ppFilter) +{ + IFilterGraphImpl *This = impl_from_IFilterGraph2(iface); HRESULT hr; IBaseFilter* preader; IFileSourceFilter* pfile = NULL; @@ -1557,9 +1661,6 @@ static HRESULT WINAPI FilterGraph2_AddSourceFilter(IFilterGraph2 *iface, /* Try from file name first, then fall back to default asynchronous reader */ hr = GetFileSourceFilter(lpcwstrFileName, &preader); - - if (FAILED(hr)) - hr = CoCreateInstance(&CLSID_AsyncReader, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&preader); if (FAILED(hr)) { WARN("Unable to create file source filter (%x)\n", hr); return hr; @@ -1578,13 +1679,7 @@ static HRESULT WINAPI FilterGraph2_AddSourceFilter(IFilterGraph2 *iface, goto error; } - /* Load the file in the file source filter */ - hr = IFileSourceFilter_Load(pfile, lpcwstrFileName, NULL); - if (FAILED(hr)) { - WARN("Load (%x)\n", hr); - goto error; - } - + /* The file has been already loaded */ IFileSourceFilter_GetCurFile(pfile, &filename, &mt); if (FAILED(hr)) { WARN("GetCurFile (%x)\n", hr); @@ -1600,35 +1695,37 @@ static HRESULT WINAPI FilterGraph2_AddSourceFilter(IFilterGraph2 *iface, IFileSourceFilter_Release(pfile); return S_OK; - + error: if (pfile) IFileSourceFilter_Release(pfile); IFilterGraph2_RemoveFilter(iface, preader); IBaseFilter_Release(preader); - + return hr; } -static HRESULT WINAPI FilterGraph2_SetLogFile(IFilterGraph2 *iface, - DWORD_PTR hFile) { - ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); +static HRESULT WINAPI FilterGraph2_SetLogFile(IFilterGraph2 *iface, DWORD_PTR hFile) +{ + IFilterGraphImpl *This = impl_from_IFilterGraph2(iface); TRACE("(%p/%p)->(%08x): stub !!!\n", This, iface, (DWORD) hFile); return S_OK; } -static HRESULT WINAPI FilterGraph2_Abort(IFilterGraph2 *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); +static HRESULT WINAPI FilterGraph2_Abort(IFilterGraph2 *iface) +{ + IFilterGraphImpl *This = impl_from_IFilterGraph2(iface); TRACE("(%p/%p)->(): stub !!!\n", This, iface); return S_OK; } -static HRESULT WINAPI FilterGraph2_ShouldOperationContinue(IFilterGraph2 *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); +static HRESULT WINAPI FilterGraph2_ShouldOperationContinue(IFilterGraph2 *iface) +{ + IFilterGraphImpl *This = impl_from_IFilterGraph2(iface); TRACE("(%p/%p)->(): stub !!!\n", This, iface); @@ -1637,32 +1734,29 @@ static HRESULT WINAPI FilterGraph2_ShouldOperationContinue(IFilterGraph2 *iface) /*** IFilterGraph2 methods ***/ static HRESULT WINAPI FilterGraph2_AddSourceFilterForMoniker(IFilterGraph2 *iface, - IMoniker *pMoniker, - IBindCtx *pCtx, - LPCWSTR lpcwstrFilterName, - IBaseFilter **ppFilter) { - ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); + IMoniker *pMoniker, IBindCtx *pCtx, LPCWSTR lpcwstrFilterName, IBaseFilter **ppFilter) +{ + IFilterGraphImpl *This = impl_from_IFilterGraph2(iface); TRACE("(%p/%p)->(%p %p %s %p): stub !!!\n", This, iface, pMoniker, pCtx, debugstr_w(lpcwstrFilterName), ppFilter); return S_OK; } -static HRESULT WINAPI FilterGraph2_ReconnectEx(IFilterGraph2 *iface, - IPin *ppin, - const AM_MEDIA_TYPE *pmt) { - ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); +static HRESULT WINAPI FilterGraph2_ReconnectEx(IFilterGraph2 *iface, IPin *ppin, + const AM_MEDIA_TYPE *pmt) +{ + IFilterGraphImpl *This = impl_from_IFilterGraph2(iface); TRACE("(%p/%p)->(%p %p): stub !!!\n", This, iface, ppin, pmt); return S_OK; } -static HRESULT WINAPI FilterGraph2_RenderEx(IFilterGraph2 *iface, - IPin *pPinOut, - DWORD dwFlags, - DWORD *pvContext) { - ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface); +static HRESULT WINAPI FilterGraph2_RenderEx(IFilterGraph2 *iface, IPin *pPinOut, DWORD dwFlags, + DWORD *pvContext) +{ + IFilterGraphImpl *This = impl_from_IFilterGraph2(iface); TRACE("(%p/%p)->(%p %08x %p): stub !!!\n", This, iface, pPinOut, dwFlags, pvContext); @@ -1695,78 +1789,74 @@ static const IFilterGraph2Vtbl IFilterGraph2_VTable = FilterGraph2_RenderEx }; -/*** IUnknown methods ***/ -static HRESULT WINAPI MediaControl_QueryInterface(IMediaControl *iface, - REFIID riid, - LPVOID*ppvObj) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); +static inline IFilterGraphImpl *impl_from_IMediaControl(IMediaControl *iface) +{ + return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaControl_iface); +} + +static HRESULT WINAPI MediaControl_QueryInterface(IMediaControl *iface, REFIID riid, void **ppvObj) +{ + IFilterGraphImpl *This = impl_from_IMediaControl(iface); TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); - return Filtergraph_QueryInterface(This, riid, ppvObj); + return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj); } -static ULONG WINAPI MediaControl_AddRef(IMediaControl *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); +static ULONG WINAPI MediaControl_AddRef(IMediaControl *iface) +{ + IFilterGraphImpl *This = impl_from_IMediaControl(iface); TRACE("(%p/%p)->()\n", This, iface); - return Filtergraph_AddRef(This); + return IUnknown_AddRef(This->outer_unk); } -static ULONG WINAPI MediaControl_Release(IMediaControl *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); +static ULONG WINAPI MediaControl_Release(IMediaControl *iface) +{ + IFilterGraphImpl *This = impl_from_IMediaControl(iface); TRACE("(%p/%p)->()\n", This, iface); - return Filtergraph_Release(This); + return IUnknown_Release(This->outer_unk); } /*** IDispatch methods ***/ -static HRESULT WINAPI MediaControl_GetTypeInfoCount(IMediaControl *iface, - UINT*pctinfo) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); +static HRESULT WINAPI MediaControl_GetTypeInfoCount(IMediaControl *iface, UINT *pctinfo) +{ + IFilterGraphImpl *This = impl_from_IMediaControl(iface); TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo); return S_OK; } -static HRESULT WINAPI MediaControl_GetTypeInfo(IMediaControl *iface, - UINT iTInfo, - LCID lcid, - ITypeInfo**ppTInfo) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); +static HRESULT WINAPI MediaControl_GetTypeInfo(IMediaControl *iface, UINT iTInfo, LCID lcid, + ITypeInfo **ppTInfo) +{ + IFilterGraphImpl *This = impl_from_IMediaControl(iface); TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo); return S_OK; } -static HRESULT WINAPI MediaControl_GetIDsOfNames(IMediaControl *iface, - REFIID riid, - LPOLESTR*rgszNames, - UINT cNames, - LCID lcid, - DISPID*rgDispId) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); +static HRESULT WINAPI MediaControl_GetIDsOfNames(IMediaControl *iface, REFIID riid, + LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) +{ + IFilterGraphImpl *This = impl_from_IMediaControl(iface); TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId); return S_OK; } -static HRESULT WINAPI MediaControl_Invoke(IMediaControl *iface, - DISPID dispIdMember, - REFIID riid, - LCID lcid, - WORD wFlags, - DISPPARAMS*pDispParams, - VARIANT*pVarResult, - EXCEPINFO*pExepInfo, - UINT*puArgErr) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); +static HRESULT WINAPI MediaControl_Invoke(IMediaControl *iface, DISPID dispIdMember, REFIID riid, + LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo, + UINT *puArgErr) +{ + IFilterGraphImpl *This = impl_from_IMediaControl(iface); TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr); @@ -1810,8 +1900,8 @@ static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundF for(i = 0; i < nb; i++) { /* Explore the graph downstream from this pin - * FIXME: We should prevent exploring from a pin more than once. This can happens when - * several input pins are connected to the same output (a MUX for instance). */ + * FIXME: We should prevent exploring from a pin more than once. This can happens when + * several input pins are connected to the same output (a MUX for instance). */ ExploreGraph(pGraph, ppPins[i], FoundFilter, data); IPin_Release(ppPins[i]); } @@ -1829,21 +1919,7 @@ static HRESULT ExploreGraph(IFilterGraphImpl* pGraph, IPin* pOutputPin, fnFoundF static HRESULT WINAPI SendRun(IBaseFilter *pFilter, DWORD_PTR data) { - LONGLONG time = 0; - IReferenceClock *clock = NULL; - - IBaseFilter_GetSyncSource(pFilter, &clock); - if (clock) - { - IReferenceClock_GetTime(clock, &time); - if (time) - /* Add 50 ms */ - time += 500000; - if (time < 0) - time = 0; - IReferenceClock_Release(clock); - } - + REFERENCE_TIME time = *(REFERENCE_TIME*)data; return IBaseFilter_Run(pFilter, time); } @@ -1879,9 +1955,8 @@ static HRESULT WINAPI SendGetState(IBaseFilter *pFilter, DWORD_PTR data) } -static HRESULT SendFilterMessage(IMediaControl *iface, fnFoundFilter FoundFilter, DWORD_PTR data) +static HRESULT SendFilterMessage(IFilterGraphImpl *This, fnFoundFilter FoundFilter, DWORD_PTR data) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); int i; IBaseFilter* pfilter; IEnumPins* pEnum; @@ -1889,7 +1964,8 @@ static HRESULT SendFilterMessage(IMediaControl *iface, fnFoundFilter FoundFilter IPin* pPin; DWORD dummy; PIN_DIRECTION dir; - TRACE("(%p/%p)->()\n", This, iface); + + TRACE("(%p)->()\n", This); /* Explorer the graph from source filters to renderers, determine renderers * number and run filters from renderers to source filters */ @@ -1936,77 +2012,82 @@ static HRESULT SendFilterMessage(IMediaControl *iface, fnFoundFilter FoundFilter } /*** IMediaControl methods ***/ -static HRESULT WINAPI MediaControl_Run(IMediaControl *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); +static HRESULT WINAPI MediaControl_Run(IMediaControl *iface) +{ + IFilterGraphImpl *This = impl_from_IMediaControl(iface); + TRACE("(%p/%p)->()\n", This, iface); - if (This->state == State_Running) return S_OK; - EnterCriticalSection(&This->cs); - if (This->state == State_Stopped) - This->EcCompleteCount = 0; + if (This->state == State_Running) + goto out; + This->EcCompleteCount = 0; + + if (This->defaultclock && !This->refClock) + IFilterGraph2_SetDefaultSyncSource(&This->IFilterGraph2_iface); if (This->refClock) { - IReferenceClock_GetTime(This->refClock, &This->start_time); - This->start_time += 500000; + REFERENCE_TIME now; + IReferenceClock_GetTime(This->refClock, &now); + if (This->state == State_Stopped) + This->start_time = now + 500000; + else if (This->pause_time >= 0) + This->start_time += now - This->pause_time; + else + This->start_time = now; } - else This->position = This->start_time = 0; + else This->start_time = 0; - SendFilterMessage(iface, SendRun, 0); + SendFilterMessage(This, SendRun, (DWORD_PTR)&This->start_time); This->state = State_Running; +out: LeaveCriticalSection(&This->cs); return S_FALSE; } -static HRESULT WINAPI MediaControl_Pause(IMediaControl *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); +static HRESULT WINAPI MediaControl_Pause(IMediaControl *iface) +{ + IFilterGraphImpl *This = impl_from_IMediaControl(iface); + TRACE("(%p/%p)->()\n", This, iface); - if (This->state == State_Paused) return S_OK; - EnterCriticalSection(&This->cs); - if (This->state == State_Stopped) - This->EcCompleteCount = 0; + if (This->state == State_Paused) + goto out; - if (This->state == State_Running && This->refClock) - { - LONGLONG time = This->start_time; - IReferenceClock_GetTime(This->refClock, &time); - This->position += time - This->start_time; - } + if (This->state == State_Running && This->refClock && This->start_time >= 0) + IReferenceClock_GetTime(This->refClock, &This->pause_time); + else + This->pause_time = -1; - SendFilterMessage(iface, SendPause, 0); + SendFilterMessage(This, SendPause, 0); This->state = State_Paused; +out: LeaveCriticalSection(&This->cs); return S_FALSE; } -static HRESULT WINAPI MediaControl_Stop(IMediaControl *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); +static HRESULT WINAPI MediaControl_Stop(IMediaControl *iface) +{ + IFilterGraphImpl *This = impl_from_IMediaControl(iface); + TRACE("(%p/%p)->()\n", This, iface); if (This->state == State_Stopped) return S_OK; EnterCriticalSection(&This->cs); - if (This->state == State_Running && This->refClock) - { - LONGLONG time = This->start_time; - IReferenceClock_GetTime(This->refClock, &time); - This->position += time - This->start_time; - } - - if (This->state == State_Running) SendFilterMessage(iface, SendPause, 0); - SendFilterMessage(iface, SendStop, 0); + if (This->state == State_Running) SendFilterMessage(This, SendPause, 0); + SendFilterMessage(This, SendStop, 0); This->state = State_Stopped; LeaveCriticalSection(&This->cs); return S_OK; } -static HRESULT WINAPI MediaControl_GetState(IMediaControl *iface, - LONG msTimeout, - OAFilterState *pfs) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); +static HRESULT WINAPI MediaControl_GetState(IMediaControl *iface, LONG msTimeout, + OAFilterState *pfs) +{ + IFilterGraphImpl *This = impl_from_IMediaControl(iface); DWORD end; TRACE("(%p/%p)->(%d, %p)\n", This, iface, msTimeout, pfs); @@ -2030,52 +2111,53 @@ static HRESULT WINAPI MediaControl_GetState(IMediaControl *iface, end = 0; } if (end) - SendFilterMessage(iface, SendGetState, end); + SendFilterMessage(This, SendGetState, end); LeaveCriticalSection(&This->cs); return S_OK; } -static HRESULT WINAPI MediaControl_RenderFile(IMediaControl *iface, - BSTR strFilename) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); +static HRESULT WINAPI MediaControl_RenderFile(IMediaControl *iface, BSTR strFilename) +{ + IFilterGraphImpl *This = impl_from_IMediaControl(iface); - FIXME("(%p/%p)->(%s (%p)): stub !!!\n", This, iface, debugstr_w(strFilename), strFilename); + TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strFilename), strFilename); - return S_OK; + return IFilterGraph2_RenderFile(&This->IFilterGraph2_iface, strFilename, NULL); } -static HRESULT WINAPI MediaControl_AddSourceFilter(IMediaControl *iface, - BSTR strFilename, - IDispatch **ppUnk) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); +static HRESULT WINAPI MediaControl_AddSourceFilter(IMediaControl *iface, BSTR strFilename, + IDispatch **ppUnk) +{ + IFilterGraphImpl *This = impl_from_IMediaControl(iface); FIXME("(%p/%p)->(%s (%p), %p): stub !!!\n", This, iface, debugstr_w(strFilename), strFilename, ppUnk); return S_OK; } -static HRESULT WINAPI MediaControl_get_FilterCollection(IMediaControl *iface, - IDispatch **ppUnk) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); +static HRESULT WINAPI MediaControl_get_FilterCollection(IMediaControl *iface, IDispatch **ppUnk) +{ + IFilterGraphImpl *This = impl_from_IMediaControl(iface); FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk); return S_OK; } -static HRESULT WINAPI MediaControl_get_RegFilterCollection(IMediaControl *iface, - IDispatch **ppUnk) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); +static HRESULT WINAPI MediaControl_get_RegFilterCollection(IMediaControl *iface, IDispatch **ppUnk) +{ + IFilterGraphImpl *This = impl_from_IMediaControl(iface); FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, ppUnk); return S_OK; } -static HRESULT WINAPI MediaControl_StopWhenReady(IMediaControl *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface); +static HRESULT WINAPI MediaControl_StopWhenReady(IMediaControl *iface) +{ + IFilterGraphImpl *This = impl_from_IMediaControl(iface); FIXME("(%p/%p)->(): stub !!!\n", This, iface); @@ -2103,32 +2185,36 @@ static const IMediaControlVtbl IMediaControl_VTable = MediaControl_StopWhenReady }; +static inline IFilterGraphImpl *impl_from_IMediaSeeking(IMediaSeeking *iface) +{ + return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaSeeking_iface); +} -/*** IUnknown methods ***/ -static HRESULT WINAPI MediaSeeking_QueryInterface(IMediaSeeking *iface, - REFIID riid, - LPVOID*ppvObj) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); +static HRESULT WINAPI MediaSeeking_QueryInterface(IMediaSeeking *iface, REFIID riid, void **ppvObj) +{ + IFilterGraphImpl *This = impl_from_IMediaSeeking(iface); TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); - return Filtergraph_QueryInterface(This, riid, ppvObj); + return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj); } -static ULONG WINAPI MediaSeeking_AddRef(IMediaSeeking *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); +static ULONG WINAPI MediaSeeking_AddRef(IMediaSeeking *iface) +{ + IFilterGraphImpl *This = impl_from_IMediaSeeking(iface); TRACE("(%p/%p)->()\n", This, iface); - return Filtergraph_AddRef(This); + return IUnknown_AddRef(This->outer_unk); } -static ULONG WINAPI MediaSeeking_Release(IMediaSeeking *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); +static ULONG WINAPI MediaSeeking_Release(IMediaSeeking *iface) +{ + IFilterGraphImpl *This = impl_from_IMediaSeeking(iface); TRACE("(%p/%p)->()\n", This, iface); - return Filtergraph_Release(This); + return IUnknown_Release(This->outer_unk); } typedef HRESULT (WINAPI *fnFoundSeek)(IFilterGraphImpl *This, IMediaSeeking*, DWORD_PTR arg); @@ -2136,53 +2222,34 @@ typedef HRESULT (WINAPI *fnFoundSeek)(IFilterGraphImpl *This, IMediaSeeking*, DW static HRESULT all_renderers_seek(IFilterGraphImpl *This, fnFoundSeek FoundSeek, DWORD_PTR arg) { BOOL allnotimpl = TRUE; int i; - IBaseFilter* pfilter; - IEnumPins* pEnum; HRESULT hr, hr_return = S_OK; - IPin* pPin; - DWORD dummy; - PIN_DIRECTION dir; TRACE("(%p)->(%p %08lx)\n", This, FoundSeek, arg); /* Send a message to all renderers, they are responsible for broadcasting it further */ for(i = 0; i < This->nFilters; i++) { - BOOL renderer = TRUE; - pfilter = This->ppFiltersInGraph[i]; - hr = IBaseFilter_EnumPins(pfilter, &pEnum); - if (hr != S_OK) - { - WARN("Enum pins failed %x\n", hr); + IMediaSeeking *seek = NULL; + IBaseFilter* pfilter = This->ppFiltersInGraph[i]; + IAMFilterMiscFlags *flags = NULL; + ULONG filterflags; + IBaseFilter_QueryInterface(pfilter, &IID_IAMFilterMiscFlags, (void**)&flags); + if (!flags) + continue; + filterflags = IAMFilterMiscFlags_GetMiscFlags(flags); + IAMFilterMiscFlags_Release(flags); + if (filterflags != AM_FILTER_MISC_FLAGS_IS_RENDERER) continue; - } - /* Check if it is a source filter */ - while(IEnumPins_Next(pEnum, 1, &pPin, &dummy) == S_OK) - { - IPin_QueryDirection(pPin, &dir); - IPin_Release(pPin); - if (dir != PINDIR_INPUT) - { - renderer = FALSE; - break; - } - } - IEnumPins_Release(pEnum); - if (renderer) - { - IMediaSeeking *seek = NULL; - IBaseFilter_QueryInterface(pfilter, &IID_IMediaSeeking, (void**)&seek); - if (!seek) - continue; - hr = FoundSeek(This, seek, arg); - - IMediaSeeking_Release(seek); - if (hr_return != E_NOTIMPL) - allnotimpl = FALSE; - if (hr_return == S_OK || (FAILED(hr) && hr != E_NOTIMPL && SUCCEEDED(hr_return))) - hr_return = hr; - } + IBaseFilter_QueryInterface(pfilter, &IID_IMediaSeeking, (void**)&seek); + if (!seek) + continue; + hr = FoundSeek(This, seek, arg); + IMediaSeeking_Release(seek); + if (hr_return != E_NOTIMPL) + allnotimpl = FALSE; + if (hr_return == S_OK || (FAILED(hr) && hr != E_NOTIMPL && SUCCEEDED(hr_return))) + hr_return = hr; } if (allnotimpl) @@ -2206,10 +2273,11 @@ static HRESULT WINAPI FoundCapabilities(IFilterGraphImpl *This, IMediaSeeking *s } /*** IMediaSeeking methods ***/ -static HRESULT WINAPI MediaSeeking_GetCapabilities(IMediaSeeking *iface, - DWORD *pCapabilities) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); +static HRESULT WINAPI MediaSeeking_GetCapabilities(IMediaSeeking *iface, DWORD *pCapabilities) +{ + IFilterGraphImpl *This = impl_from_IMediaSeeking(iface); HRESULT hr; + TRACE("(%p/%p)->(%p)\n", This, iface, pCapabilities); if (!pCapabilities) @@ -2224,11 +2292,12 @@ static HRESULT WINAPI MediaSeeking_GetCapabilities(IMediaSeeking *iface, return hr; } -static HRESULT WINAPI MediaSeeking_CheckCapabilities(IMediaSeeking *iface, - DWORD *pCapabilities) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); +static HRESULT WINAPI MediaSeeking_CheckCapabilities(IMediaSeeking *iface, DWORD *pCapabilities) +{ + IFilterGraphImpl *This = impl_from_IMediaSeeking(iface); DWORD originalcaps; HRESULT hr; + TRACE("(%p/%p)->(%p)\n", This, iface, pCapabilities); if (!pCapabilities) @@ -2249,9 +2318,9 @@ static HRESULT WINAPI MediaSeeking_CheckCapabilities(IMediaSeeking *iface, return S_OK; } -static HRESULT WINAPI MediaSeeking_IsFormatSupported(IMediaSeeking *iface, - const GUID *pFormat) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); +static HRESULT WINAPI MediaSeeking_IsFormatSupported(IMediaSeeking *iface, const GUID *pFormat) +{ + IFilterGraphImpl *This = impl_from_IMediaSeeking(iface); if (!pFormat) return E_POINTER; @@ -2267,9 +2336,9 @@ static HRESULT WINAPI MediaSeeking_IsFormatSupported(IMediaSeeking *iface, return S_OK; } -static HRESULT WINAPI MediaSeeking_QueryPreferredFormat(IMediaSeeking *iface, - GUID *pFormat) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); +static HRESULT WINAPI MediaSeeking_QueryPreferredFormat(IMediaSeeking *iface, GUID *pFormat) +{ + IFilterGraphImpl *This = impl_from_IMediaSeeking(iface); if (!pFormat) return E_POINTER; @@ -2280,9 +2349,9 @@ static HRESULT WINAPI MediaSeeking_QueryPreferredFormat(IMediaSeeking *iface, return S_OK; } -static HRESULT WINAPI MediaSeeking_GetTimeFormat(IMediaSeeking *iface, - GUID *pFormat) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); +static HRESULT WINAPI MediaSeeking_GetTimeFormat(IMediaSeeking *iface, GUID *pFormat) +{ + IFilterGraphImpl *This = impl_from_IMediaSeeking(iface); if (!pFormat) return E_POINTER; @@ -2293,9 +2362,9 @@ static HRESULT WINAPI MediaSeeking_GetTimeFormat(IMediaSeeking *iface, return S_OK; } -static HRESULT WINAPI MediaSeeking_IsUsingTimeFormat(IMediaSeeking *iface, - const GUID *pFormat) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); +static HRESULT WINAPI MediaSeeking_IsUsingTimeFormat(IMediaSeeking *iface, const GUID *pFormat) +{ + IFilterGraphImpl *This = impl_from_IMediaSeeking(iface); TRACE("(%p/%p)->(%p)\n", This, iface, pFormat); if (!pFormat) @@ -2307,9 +2376,9 @@ static HRESULT WINAPI MediaSeeking_IsUsingTimeFormat(IMediaSeeking *iface, return S_OK; } -static HRESULT WINAPI MediaSeeking_SetTimeFormat(IMediaSeeking *iface, - const GUID *pFormat) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); +static HRESULT WINAPI MediaSeeking_SetTimeFormat(IMediaSeeking *iface, const GUID *pFormat) +{ + IFilterGraphImpl *This = impl_from_IMediaSeeking(iface); if (!pFormat) return E_POINTER; @@ -2337,16 +2406,14 @@ static HRESULT WINAPI FoundDuration(IFilterGraphImpl *This, IMediaSeeking *seek, if (FAILED(hr)) return hr; - /* FIXME: Minimum or maximum duration? Assuming minimum */ - if (duration > 0 && *pdur < duration) + if (*pdur < duration) *pdur = duration; - return hr; } -static HRESULT WINAPI MediaSeeking_GetDuration(IMediaSeeking *iface, - LONGLONG *pDuration) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); +static HRESULT WINAPI MediaSeeking_GetDuration(IMediaSeeking *iface, LONGLONG *pDuration) +{ + IFilterGraphImpl *This = impl_from_IMediaSeeking(iface); HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, pDuration); @@ -2355,7 +2422,7 @@ static HRESULT WINAPI MediaSeeking_GetDuration(IMediaSeeking *iface, return E_POINTER; EnterCriticalSection(&This->cs); - *pDuration = -1; + *pDuration = 0; hr = all_renderers_seek(This, FoundDuration, (DWORD_PTR)pDuration); LeaveCriticalSection(&This->cs); @@ -2363,9 +2430,9 @@ static HRESULT WINAPI MediaSeeking_GetDuration(IMediaSeeking *iface, return hr; } -static HRESULT WINAPI MediaSeeking_GetStopPosition(IMediaSeeking *iface, - LONGLONG *pStop) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); +static HRESULT WINAPI MediaSeeking_GetStopPosition(IMediaSeeking *iface, LONGLONG *pStop) +{ + IFilterGraphImpl *This = impl_from_IMediaSeeking(iface); HRESULT hr = S_OK; TRACE("(%p/%p)->(%p)\n", This, iface, pStop); @@ -2379,32 +2446,29 @@ static HRESULT WINAPI MediaSeeking_GetStopPosition(IMediaSeeking *iface, hr = IMediaSeeking_GetDuration(iface, pStop); else *pStop = This->stop_position; - LeaveCriticalSection(&This->cs); return hr; } -static HRESULT WINAPI MediaSeeking_GetCurrentPosition(IMediaSeeking *iface, - LONGLONG *pCurrent) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); +static HRESULT WINAPI MediaSeeking_GetCurrentPosition(IMediaSeeking *iface, LONGLONG *pCurrent) +{ + IFilterGraphImpl *This = impl_from_IMediaSeeking(iface); LONGLONG time = 0; if (!pCurrent) return E_POINTER; EnterCriticalSection(&This->cs); - if (This->state == State_Running && This->refClock) + if (This->state == State_Running && This->refClock && This->start_time >= 0) { IReferenceClock_GetTime(This->refClock, &time); if (time) - time += This->position - This->start_time; - if (time < This->position) - time = This->position; - *pCurrent = time; + time -= This->start_time; } - else - *pCurrent = This->position; + if (This->pause_time > 0) + time += This->pause_time; + *pCurrent = time; LeaveCriticalSection(&This->cs); TRACE("Time: %u.%03u\n", (DWORD)(*pCurrent / 10000000), (DWORD)((*pCurrent / 10000)%1000)); @@ -2412,12 +2476,10 @@ static HRESULT WINAPI MediaSeeking_GetCurrentPosition(IMediaSeeking *iface, return S_OK; } -static HRESULT WINAPI MediaSeeking_ConvertTimeFormat(IMediaSeeking *iface, - LONGLONG *pTarget, - const GUID *pTargetFormat, - LONGLONG Source, - const GUID *pSourceFormat) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); +static HRESULT WINAPI MediaSeeking_ConvertTimeFormat(IMediaSeeking *iface, LONGLONG *pTarget, + const GUID *pTargetFormat, LONGLONG Source, const GUID *pSourceFormat) +{ + IFilterGraphImpl *This = impl_from_IMediaSeeking(iface); FIXME("(%p/%p)->(%p, %p, 0x%s, %p): stub !!!\n", This, iface, pTarget, pTargetFormat, wine_dbgstr_longlong(Source), pSourceFormat); @@ -2437,12 +2499,10 @@ static HRESULT WINAPI found_setposition(IFilterGraphImpl *This, IMediaSeeking *s return IMediaSeeking_SetPositions(seek, args->current, args->curflags, args->stop, args->stopflags); } -static HRESULT WINAPI MediaSeeking_SetPositions(IMediaSeeking *iface, - LONGLONG *pCurrent, - DWORD dwCurrentFlags, - LONGLONG *pStop, - DWORD dwStopFlags) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); +static HRESULT WINAPI MediaSeeking_SetPositions(IMediaSeeking *iface, LONGLONG *pCurrent, + DWORD dwCurrentFlags, LONGLONG *pStop, DWORD dwStopFlags) +{ + IFilterGraphImpl *This = impl_from_IMediaSeeking(iface); HRESULT hr = S_OK; FILTER_STATE state; struct pos_args args; @@ -2453,11 +2513,8 @@ static HRESULT WINAPI MediaSeeking_SetPositions(IMediaSeeking *iface, state = This->state; TRACE("State: %s\n", state == State_Running ? "Running" : (state == State_Paused ? "Paused" : (state == State_Stopped ? "Stopped" : "UNKNOWN"))); - if ((dwCurrentFlags & 0x7) == AM_SEEKING_AbsolutePositioning) - { - This->position = *pCurrent; - } - else if ((dwCurrentFlags & 0x7) != AM_SEEKING_NoPositioning) + if ((dwCurrentFlags & 0x7) != AM_SEEKING_AbsolutePositioning && + (dwCurrentFlags & 0x7) != AM_SEEKING_NoPositioning) FIXME("Adjust method %x not handled yet!\n", dwCurrentFlags & 0x7); if ((dwStopFlags & 0x7) == AM_SEEKING_AbsolutePositioning) @@ -2465,26 +2522,27 @@ static HRESULT WINAPI MediaSeeking_SetPositions(IMediaSeeking *iface, else if ((dwStopFlags & 0x7) != AM_SEEKING_NoPositioning) FIXME("Stop position not handled yet!\n"); + if (state == State_Running && !(dwCurrentFlags & AM_SEEKING_NoFlush)) + IMediaControl_Pause(&This->IMediaControl_iface); args.current = pCurrent; args.stop = pStop; args.curflags = dwCurrentFlags; args.stopflags = dwStopFlags; hr = all_renderers_seek(This, found_setposition, (DWORD_PTR)&args); - if (This->refClock && ((dwCurrentFlags & 0x7) != AM_SEEKING_NoPositioning)) - { - /* Update start time, prevents weird jumps */ - IReferenceClock_GetTime(This->refClock, &This->start_time); - } + if ((dwCurrentFlags & 0x7) != AM_SEEKING_NoPositioning) + This->pause_time = This->start_time = -1; + if (state == State_Running && !(dwCurrentFlags & AM_SEEKING_NoFlush)) + IMediaControl_Run(&This->IMediaControl_iface); LeaveCriticalSection(&This->cs); return hr; } -static HRESULT WINAPI MediaSeeking_GetPositions(IMediaSeeking *iface, - LONGLONG *pCurrent, - LONGLONG *pStop) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); +static HRESULT WINAPI MediaSeeking_GetPositions(IMediaSeeking *iface, LONGLONG *pCurrent, + LONGLONG *pStop) +{ + IFilterGraphImpl *This = impl_from_IMediaSeeking(iface); HRESULT hr; TRACE("(%p/%p)->(%p, %p)\n", This, iface, pCurrent, pStop); @@ -2495,37 +2553,37 @@ static HRESULT WINAPI MediaSeeking_GetPositions(IMediaSeeking *iface, return hr; } -static HRESULT WINAPI MediaSeeking_GetAvailable(IMediaSeeking *iface, - LONGLONG *pEarliest, - LONGLONG *pLatest) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); +static HRESULT WINAPI MediaSeeking_GetAvailable(IMediaSeeking *iface, LONGLONG *pEarliest, + LONGLONG *pLatest) +{ + IFilterGraphImpl *This = impl_from_IMediaSeeking(iface); FIXME("(%p/%p)->(%p, %p): stub !!!\n", This, iface, pEarliest, pLatest); return S_OK; } -static HRESULT WINAPI MediaSeeking_SetRate(IMediaSeeking *iface, - double dRate) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); +static HRESULT WINAPI MediaSeeking_SetRate(IMediaSeeking *iface, double dRate) +{ + IFilterGraphImpl *This = impl_from_IMediaSeeking(iface); FIXME("(%p/%p)->(%f): stub !!!\n", This, iface, dRate); return S_OK; } -static HRESULT WINAPI MediaSeeking_GetRate(IMediaSeeking *iface, - double *pdRate) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); +static HRESULT WINAPI MediaSeeking_GetRate(IMediaSeeking *iface, double *pdRate) +{ + IFilterGraphImpl *This = impl_from_IMediaSeeking(iface); FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pdRate); return S_OK; } -static HRESULT WINAPI MediaSeeking_GetPreroll(IMediaSeeking *iface, - LONGLONG *pllPreroll) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaSeeking_vtbl, iface); +static HRESULT WINAPI MediaSeeking_GetPreroll(IMediaSeeking *iface, LONGLONG *pllPreroll) +{ + IFilterGraphImpl *This = impl_from_IMediaSeeking(iface); FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pllPreroll); @@ -2557,9 +2615,9 @@ static const IMediaSeekingVtbl IMediaSeeking_VTable = MediaSeeking_GetPreroll }; -static inline IFilterGraphImpl *impl_from_IMediaPosition( IMediaPosition *iface ) +static inline IFilterGraphImpl *impl_from_IMediaPosition(IMediaPosition *iface) { - return (IFilterGraphImpl *)((char*)iface - FIELD_OFFSET(IFilterGraphImpl, IMediaPosition_vtbl)); + return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaPosition_iface); } /*** IUnknown methods ***/ @@ -2568,7 +2626,8 @@ static HRESULT WINAPI MediaPosition_QueryInterface(IMediaPosition* iface, REFIID IFilterGraphImpl *This = impl_from_IMediaPosition( iface ); TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); - return Filtergraph_QueryInterface(This, riid, ppvObj); + + return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj); } static ULONG WINAPI MediaPosition_AddRef(IMediaPosition *iface) @@ -2576,7 +2635,8 @@ static ULONG WINAPI MediaPosition_AddRef(IMediaPosition *iface) IFilterGraphImpl *This = impl_from_IMediaPosition( iface ); TRACE("(%p/%p)->()\n", This, iface); - return Filtergraph_AddRef(This); + + return IUnknown_AddRef(This->outer_unk); } static ULONG WINAPI MediaPosition_Release(IMediaPosition *iface) @@ -2584,84 +2644,138 @@ static ULONG WINAPI MediaPosition_Release(IMediaPosition *iface) IFilterGraphImpl *This = impl_from_IMediaPosition( iface ); TRACE("(%p/%p)->()\n", This, iface); - return Filtergraph_Release(This); + + return IUnknown_Release(This->outer_unk); } /*** IDispatch methods ***/ -static HRESULT WINAPI MediaPosition_GetTypeInfoCount(IMediaPosition *iface, UINT* pctinfo){ +static HRESULT WINAPI MediaPosition_GetTypeInfoCount(IMediaPosition *iface, UINT* pctinfo) +{ FIXME("(%p) stub!\n", iface); return E_NOTIMPL; } -static HRESULT WINAPI MediaPosition_GetTypeInfo(IMediaPosition *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo){ +static HRESULT WINAPI MediaPosition_GetTypeInfo(IMediaPosition *iface, UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) +{ FIXME("(%p) stub!\n", iface); return E_NOTIMPL; } -static HRESULT WINAPI MediaPosition_GetIDsOfNames(IMediaPosition* iface, REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId){ +static HRESULT WINAPI MediaPosition_GetIDsOfNames(IMediaPosition* iface, REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) +{ FIXME("(%p) stub!\n", iface); return E_NOTIMPL; } -static HRESULT WINAPI MediaPosition_Invoke(IMediaPosition* iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr){ +static HRESULT WINAPI MediaPosition_Invoke(IMediaPosition* iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) +{ FIXME("(%p) stub!\n", iface); return E_NOTIMPL; } +static HRESULT ConvertFromREFTIME(IMediaSeeking *seek, REFTIME time_in, LONGLONG *time_out) +{ + GUID time_format; + HRESULT hr; + + hr = MediaSeeking_GetTimeFormat(seek, &time_format); + if (FAILED(hr)) + return hr; + if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, &time_format)) + { + FIXME("Unsupported time format.\n"); + return E_NOTIMPL; + } + + *time_out = (LONGLONG) (time_in * 10000000); /* convert from 1 second intervals to 100 ns intervals */ + return S_OK; +} + +static HRESULT ConvertToREFTIME(IMediaSeeking *seek, LONGLONG time_in, REFTIME *time_out) +{ + GUID time_format; + HRESULT hr; + + hr = MediaSeeking_GetTimeFormat(seek, &time_format); + if (FAILED(hr)) + return hr; + if (!IsEqualGUID(&TIME_FORMAT_MEDIA_TIME, &time_format)) + { + FIXME("Unsupported time format.\n"); + return E_NOTIMPL; + } + + *time_out = (REFTIME)time_in / 10000000; /* convert from 100 ns intervals to 1 second intervals */ + return S_OK; +} + /*** IMediaPosition methods ***/ static HRESULT WINAPI MediaPosition_get_Duration(IMediaPosition * iface, REFTIME *plength) { LONGLONG duration; IFilterGraphImpl *This = impl_from_IMediaPosition( iface ); - HRESULT hr = IMediaSeeking_GetDuration( (IMediaSeeking *)&This->IMediaSeeking_vtbl, &duration ); - if (SUCCEEDED(hr)) *plength = duration; - return hr; + HRESULT hr = IMediaSeeking_GetDuration(&This->IMediaSeeking_iface, &duration); + if (FAILED(hr)) + return hr; + return ConvertToREFTIME(&This->IMediaSeeking_iface, duration, plength); } static HRESULT WINAPI MediaPosition_put_CurrentPosition(IMediaPosition * iface, REFTIME llTime) { IFilterGraphImpl *This = impl_from_IMediaPosition( iface ); - LONGLONG reftime = llTime; + LONGLONG reftime; + HRESULT hr; - return IMediaSeeking_SetPositions((IMediaSeeking *)&This->IMediaSeeking_vtbl, - &reftime, AM_SEEKING_AbsolutePositioning, - NULL, AM_SEEKING_NoPositioning); + hr = ConvertFromREFTIME(&This->IMediaSeeking_iface, llTime, &reftime); + if (FAILED(hr)) + return hr; + return IMediaSeeking_SetPositions(&This->IMediaSeeking_iface, &reftime, + AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning); } static HRESULT WINAPI MediaPosition_get_CurrentPosition(IMediaPosition * iface, REFTIME *pllTime) { IFilterGraphImpl *This = impl_from_IMediaPosition( iface ); LONGLONG pos; - HRESULT hr = IMediaSeeking_GetCurrentPosition( (IMediaSeeking *)&This->IMediaSeeking_vtbl, &pos ); - if (SUCCEEDED(hr)) *pllTime = pos; - return hr; + HRESULT hr; + + hr = IMediaSeeking_GetCurrentPosition(&This->IMediaSeeking_iface, &pos); + if (FAILED(hr)) + return hr; + return ConvertToREFTIME(&This->IMediaSeeking_iface, pos, pllTime); } static HRESULT WINAPI MediaPosition_get_StopTime(IMediaPosition * iface, REFTIME *pllTime) { IFilterGraphImpl *This = impl_from_IMediaPosition( iface ); LONGLONG pos; - HRESULT hr = IMediaSeeking_GetStopPosition( (IMediaSeeking *)&This->IMediaSeeking_vtbl, &pos ); - if (SUCCEEDED(hr)) *pllTime = pos; - return hr; + HRESULT hr = IMediaSeeking_GetStopPosition(&This->IMediaSeeking_iface, &pos); + if (FAILED(hr)) + return hr; + return ConvertToREFTIME(&This->IMediaSeeking_iface, pos, pllTime); } static HRESULT WINAPI MediaPosition_put_StopTime(IMediaPosition * iface, REFTIME llTime) { IFilterGraphImpl *This = impl_from_IMediaPosition( iface ); - LONGLONG reftime = llTime; + LONGLONG reftime; + HRESULT hr; - return IMediaSeeking_SetPositions((IMediaSeeking *)&This->IMediaSeeking_vtbl, - NULL, AM_SEEKING_NoPositioning, - &reftime, AM_SEEKING_AbsolutePositioning); + hr = ConvertFromREFTIME(&This->IMediaSeeking_iface, llTime, &reftime); + if (FAILED(hr)) + return hr; + return IMediaSeeking_SetPositions(&This->IMediaSeeking_iface, NULL, AM_SEEKING_NoPositioning, + &reftime, AM_SEEKING_AbsolutePositioning); } -static HRESULT WINAPI MediaPosition_get_PrerollTime(IMediaPosition * iface, REFTIME *pllTime){ +static HRESULT WINAPI MediaPosition_get_PrerollTime(IMediaPosition * iface, REFTIME *pllTime) +{ FIXME("(%p)->(%p) stub!\n", iface, pllTime); return E_NOTIMPL; } -static HRESULT WINAPI MediaPosition_put_PrerollTime(IMediaPosition * iface, REFTIME llTime){ +static HRESULT WINAPI MediaPosition_put_PrerollTime(IMediaPosition * iface, REFTIME llTime) +{ FIXME("(%p)->(%f) stub!\n", iface, llTime); return E_NOTIMPL; } @@ -2669,21 +2783,23 @@ static HRESULT WINAPI MediaPosition_put_PrerollTime(IMediaPosition * iface, REFT static HRESULT WINAPI MediaPosition_put_Rate(IMediaPosition * iface, double dRate) { IFilterGraphImpl *This = impl_from_IMediaPosition( iface ); - return IMediaSeeking_SetRate((IMediaSeeking *)&This->IMediaSeeking_vtbl, dRate); + return IMediaSeeking_SetRate(&This->IMediaSeeking_iface, dRate); } static HRESULT WINAPI MediaPosition_get_Rate(IMediaPosition * iface, double *pdRate) { IFilterGraphImpl *This = impl_from_IMediaPosition( iface ); - return IMediaSeeking_GetRate((IMediaSeeking *)&This->IMediaSeeking_vtbl, pdRate); + return IMediaSeeking_GetRate(&This->IMediaSeeking_iface, pdRate); } -static HRESULT WINAPI MediaPosition_CanSeekForward(IMediaPosition * iface, LONG *pCanSeekForward){ +static HRESULT WINAPI MediaPosition_CanSeekForward(IMediaPosition * iface, LONG *pCanSeekForward) +{ FIXME("(%p)->(%p) stub!\n", iface, pCanSeekForward); return E_NOTIMPL; } -static HRESULT WINAPI MediaPosition_CanSeekBackward(IMediaPosition * iface, LONG *pCanSeekBackward){ +static HRESULT WINAPI MediaPosition_CanSeekBackward(IMediaPosition * iface, LONG *pCanSeekBackward) +{ FIXME("(%p)->(%p) stub!\n", iface, pCanSeekBackward); return E_NOTIMPL; } @@ -2711,6 +2827,74 @@ static const IMediaPositionVtbl IMediaPosition_VTable = MediaPosition_CanSeekBackward }; +static inline IFilterGraphImpl *impl_from_IObjectWithSite(IObjectWithSite *iface) +{ + return CONTAINING_RECORD(iface, IFilterGraphImpl, IObjectWithSite_iface); +} + +/*** IUnknown methods ***/ +static HRESULT WINAPI ObjectWithSite_QueryInterface(IObjectWithSite* iface, REFIID riid, void** ppvObj) +{ + IFilterGraphImpl *This = impl_from_IObjectWithSite( iface ); + + TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); + + return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj); +} + +static ULONG WINAPI ObjectWithSite_AddRef(IObjectWithSite *iface) +{ + IFilterGraphImpl *This = impl_from_IObjectWithSite( iface ); + + TRACE("(%p/%p)->()\n", This, iface); + + return IUnknown_AddRef(This->outer_unk); +} + +static ULONG WINAPI ObjectWithSite_Release(IObjectWithSite *iface) +{ + IFilterGraphImpl *This = impl_from_IObjectWithSite( iface ); + + TRACE("(%p/%p)->()\n", This, iface); + + return IUnknown_Release(This->outer_unk); +} + +/*** IObjectWithSite methods ***/ + +static HRESULT WINAPI ObjectWithSite_SetSite(IObjectWithSite *iface, IUnknown *pUnkSite) +{ + IFilterGraphImpl *This = impl_from_IObjectWithSite( iface ); + + TRACE("(%p/%p)->()\n", This, iface); + if (This->pSite) IUnknown_Release(This->pSite); + This->pSite = pUnkSite; + IUnknown_AddRef(This->pSite); + return S_OK; +} + +static HRESULT WINAPI ObjectWithSite_GetSite(IObjectWithSite *iface, REFIID riid, PVOID *ppvSite) +{ + IFilterGraphImpl *This = impl_from_IObjectWithSite( iface ); + + TRACE("(%p/%p)->(%s)\n", This, iface,debugstr_guid(riid)); + + *ppvSite = NULL; + if (!This->pSite) + return E_FAIL; + else + return IUnknown_QueryInterface(This->pSite, riid, ppvSite); +} + +static const IObjectWithSiteVtbl IObjectWithSite_VTable = +{ + ObjectWithSite_QueryInterface, + ObjectWithSite_AddRef, + ObjectWithSite_Release, + ObjectWithSite_SetSite, + ObjectWithSite_GetSite, +}; + static HRESULT GetTargetInterface(IFilterGraphImpl* pGraph, REFIID riid, LPVOID* ppvObj) { HRESULT hr = E_NOINTERFACE; @@ -2756,37 +2940,42 @@ static HRESULT GetTargetInterface(IFilterGraphImpl* pGraph, REFIID riid, LPVOID* return hr; } -/*** IUnknown methods ***/ -static HRESULT WINAPI BasicAudio_QueryInterface(IBasicAudio *iface, - REFIID riid, - LPVOID*ppvObj) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface); +static inline IFilterGraphImpl *impl_from_IBasicAudio(IBasicAudio *iface) +{ + return CONTAINING_RECORD(iface, IFilterGraphImpl, IBasicAudio_iface); +} + +static HRESULT WINAPI BasicAudio_QueryInterface(IBasicAudio *iface, REFIID riid, void **ppvObj) +{ + IFilterGraphImpl *This = impl_from_IBasicAudio(iface); TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); - return Filtergraph_QueryInterface(This, riid, ppvObj); + return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj); } -static ULONG WINAPI BasicAudio_AddRef(IBasicAudio *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface); +static ULONG WINAPI BasicAudio_AddRef(IBasicAudio *iface) +{ + IFilterGraphImpl *This = impl_from_IBasicAudio(iface); TRACE("(%p/%p)->()\n", This, iface); - return Filtergraph_AddRef(This); + return IUnknown_AddRef(This->outer_unk); } -static ULONG WINAPI BasicAudio_Release(IBasicAudio *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface); +static ULONG WINAPI BasicAudio_Release(IBasicAudio *iface) +{ + IFilterGraphImpl *This = impl_from_IBasicAudio(iface); TRACE("(%p/%p)->()\n", This, iface); - return Filtergraph_Release(This); + return IUnknown_Release(This->outer_unk); } /*** IDispatch methods ***/ -static HRESULT WINAPI BasicAudio_GetTypeInfoCount(IBasicAudio *iface, - UINT*pctinfo) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface); +static HRESULT WINAPI BasicAudio_GetTypeInfoCount(IBasicAudio *iface, UINT *pctinfo) +{ + IFilterGraphImpl *This = impl_from_IBasicAudio(iface); IBasicAudio* pBasicAudio; HRESULT hr; @@ -2804,11 +2993,10 @@ static HRESULT WINAPI BasicAudio_GetTypeInfoCount(IBasicAudio *iface, return hr; } -static HRESULT WINAPI BasicAudio_GetTypeInfo(IBasicAudio *iface, - UINT iTInfo, - LCID lcid, - ITypeInfo**ppTInfo) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface); +static HRESULT WINAPI BasicAudio_GetTypeInfo(IBasicAudio *iface, UINT iTInfo, LCID lcid, + ITypeInfo **ppTInfo) +{ + IFilterGraphImpl *This = impl_from_IBasicAudio(iface); IBasicAudio* pBasicAudio; HRESULT hr; @@ -2826,13 +3014,10 @@ static HRESULT WINAPI BasicAudio_GetTypeInfo(IBasicAudio *iface, return hr; } -static HRESULT WINAPI BasicAudio_GetIDsOfNames(IBasicAudio *iface, - REFIID riid, - LPOLESTR*rgszNames, - UINT cNames, - LCID lcid, - DISPID*rgDispId) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface); +static HRESULT WINAPI BasicAudio_GetIDsOfNames(IBasicAudio *iface, REFIID riid, LPOLESTR *rgszNames, + UINT cNames, LCID lcid, DISPID *rgDispId) +{ + IFilterGraphImpl *This = impl_from_IBasicAudio(iface); IBasicAudio* pBasicAudio; HRESULT hr; @@ -2850,16 +3035,11 @@ static HRESULT WINAPI BasicAudio_GetIDsOfNames(IBasicAudio *iface, return hr; } -static HRESULT WINAPI BasicAudio_Invoke(IBasicAudio *iface, - DISPID dispIdMember, - REFIID riid, - LCID lcid, - WORD wFlags, - DISPPARAMS*pDispParams, - VARIANT*pVarResult, - EXCEPINFO*pExepInfo, - UINT*puArgErr) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface); +static HRESULT WINAPI BasicAudio_Invoke(IBasicAudio *iface, DISPID dispIdMember, REFIID riid, + LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo, + UINT *puArgErr) +{ + IFilterGraphImpl *This = impl_from_IBasicAudio(iface); IBasicAudio* pBasicAudio; HRESULT hr; @@ -2878,9 +3058,9 @@ static HRESULT WINAPI BasicAudio_Invoke(IBasicAudio *iface, } /*** IBasicAudio methods ***/ -static HRESULT WINAPI BasicAudio_put_Volume(IBasicAudio *iface, - LONG lVolume) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface); +static HRESULT WINAPI BasicAudio_put_Volume(IBasicAudio *iface, LONG lVolume) +{ + IFilterGraphImpl *This = impl_from_IBasicAudio(iface); IBasicAudio* pBasicAudio; HRESULT hr; @@ -2898,9 +3078,9 @@ static HRESULT WINAPI BasicAudio_put_Volume(IBasicAudio *iface, return hr; } -static HRESULT WINAPI BasicAudio_get_Volume(IBasicAudio *iface, - LONG *plVolume) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface); +static HRESULT WINAPI BasicAudio_get_Volume(IBasicAudio *iface, LONG *plVolume) +{ + IFilterGraphImpl *This = impl_from_IBasicAudio(iface); IBasicAudio* pBasicAudio; HRESULT hr; @@ -2918,9 +3098,9 @@ static HRESULT WINAPI BasicAudio_get_Volume(IBasicAudio *iface, return hr; } -static HRESULT WINAPI BasicAudio_put_Balance(IBasicAudio *iface, - LONG lBalance) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface); +static HRESULT WINAPI BasicAudio_put_Balance(IBasicAudio *iface, LONG lBalance) +{ + IFilterGraphImpl *This = impl_from_IBasicAudio(iface); IBasicAudio* pBasicAudio; HRESULT hr; @@ -2938,9 +3118,9 @@ static HRESULT WINAPI BasicAudio_put_Balance(IBasicAudio *iface, return hr; } -static HRESULT WINAPI BasicAudio_get_Balance(IBasicAudio *iface, - LONG *plBalance) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicAudio_vtbl, iface); +static HRESULT WINAPI BasicAudio_get_Balance(IBasicAudio *iface, LONG *plBalance) +{ + IFilterGraphImpl *This = impl_from_IBasicAudio(iface); IBasicAudio* pBasicAudio; HRESULT hr; @@ -2973,38 +3153,43 @@ static const IBasicAudioVtbl IBasicAudio_VTable = BasicAudio_get_Balance }; -/*** IUnknown methods ***/ -static HRESULT WINAPI BasicVideo_QueryInterface(IBasicVideo2 *iface, - REFIID riid, - LPVOID*ppvObj) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); +static inline IFilterGraphImpl *impl_from_IBasicVideo2(IBasicVideo2 *iface) +{ + return CONTAINING_RECORD(iface, IFilterGraphImpl, IBasicVideo2_iface); +} + +static HRESULT WINAPI BasicVideo_QueryInterface(IBasicVideo2 *iface, REFIID riid, void **ppvObj) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); - return Filtergraph_QueryInterface(This, riid, ppvObj); + return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj); } -static ULONG WINAPI BasicVideo_AddRef(IBasicVideo2 *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); +static ULONG WINAPI BasicVideo_AddRef(IBasicVideo2 *iface) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); TRACE("(%p/%p)->()\n", This, iface); - return Filtergraph_AddRef(This); + return IUnknown_AddRef(This->outer_unk); } -static ULONG WINAPI BasicVideo_Release(IBasicVideo2 *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); +static ULONG WINAPI BasicVideo_Release(IBasicVideo2 *iface) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); TRACE("(%p/%p)->()\n", This, iface); - return Filtergraph_Release(This); + return IUnknown_Release(This->outer_unk); } /*** IDispatch methods ***/ -static HRESULT WINAPI BasicVideo_GetTypeInfoCount(IBasicVideo2 *iface, - UINT*pctinfo) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_GetTypeInfoCount(IBasicVideo2 *iface, UINT *pctinfo) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo); @@ -3021,12 +3206,11 @@ static HRESULT WINAPI BasicVideo_GetTypeInfoCount(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_GetTypeInfo(IBasicVideo2 *iface, - UINT iTInfo, - LCID lcid, - ITypeInfo**ppTInfo) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_GetTypeInfo(IBasicVideo2 *iface, UINT iTInfo, LCID lcid, + ITypeInfo **ppTInfo) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo); @@ -3043,14 +3227,11 @@ static HRESULT WINAPI BasicVideo_GetTypeInfo(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_GetIDsOfNames(IBasicVideo2 *iface, - REFIID riid, - LPOLESTR*rgszNames, - UINT cNames, - LCID lcid, - DISPID*rgDispId) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_GetIDsOfNames(IBasicVideo2 *iface, REFIID riid, + LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId); @@ -3067,17 +3248,12 @@ static HRESULT WINAPI BasicVideo_GetIDsOfNames(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_Invoke(IBasicVideo2 *iface, - DISPID dispIdMember, - REFIID riid, - LCID lcid, - WORD wFlags, - DISPPARAMS*pDispParams, - VARIANT*pVarResult, - EXCEPINFO*pExepInfo, - UINT*puArgErr) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_Invoke(IBasicVideo2 *iface, DISPID dispIdMember, REFIID riid, + LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo, + UINT *puArgErr) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p)\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr); @@ -3095,10 +3271,10 @@ static HRESULT WINAPI BasicVideo_Invoke(IBasicVideo2 *iface, } /*** IBasicVideo methods ***/ -static HRESULT WINAPI BasicVideo_get_AvgTimePerFrame(IBasicVideo2 *iface, - REFTIME *pAvgTimePerFrame) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_get_AvgTimePerFrame(IBasicVideo2 *iface, REFTIME *pAvgTimePerFrame) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, pAvgTimePerFrame); @@ -3115,10 +3291,10 @@ static HRESULT WINAPI BasicVideo_get_AvgTimePerFrame(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_get_BitRate(IBasicVideo2 *iface, - LONG *pBitRate) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_get_BitRate(IBasicVideo2 *iface, LONG *pBitRate) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, pBitRate); @@ -3135,10 +3311,10 @@ static HRESULT WINAPI BasicVideo_get_BitRate(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_get_BitErrorRate(IBasicVideo2 *iface, - LONG *pBitErrorRate) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_get_BitErrorRate(IBasicVideo2 *iface, LONG *pBitErrorRate) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, pBitErrorRate); @@ -3155,10 +3331,10 @@ static HRESULT WINAPI BasicVideo_get_BitErrorRate(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_get_VideoWidth(IBasicVideo2 *iface, - LONG *pVideoWidth) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_get_VideoWidth(IBasicVideo2 *iface, LONG *pVideoWidth) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, pVideoWidth); @@ -3175,10 +3351,10 @@ static HRESULT WINAPI BasicVideo_get_VideoWidth(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_get_VideoHeight(IBasicVideo2 *iface, - LONG *pVideoHeight) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_get_VideoHeight(IBasicVideo2 *iface, LONG *pVideoHeight) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, pVideoHeight); @@ -3195,10 +3371,10 @@ static HRESULT WINAPI BasicVideo_get_VideoHeight(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_put_SourceLeft(IBasicVideo2 *iface, - LONG SourceLeft) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_put_SourceLeft(IBasicVideo2 *iface, LONG SourceLeft) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%d)\n", This, iface, SourceLeft); @@ -3215,10 +3391,10 @@ static HRESULT WINAPI BasicVideo_put_SourceLeft(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_get_SourceLeft(IBasicVideo2 *iface, - LONG *pSourceLeft) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_get_SourceLeft(IBasicVideo2 *iface, LONG *pSourceLeft) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, pSourceLeft); @@ -3235,10 +3411,10 @@ static HRESULT WINAPI BasicVideo_get_SourceLeft(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_put_SourceWidth(IBasicVideo2 *iface, - LONG SourceWidth) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_put_SourceWidth(IBasicVideo2 *iface, LONG SourceWidth) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%d)\n", This, iface, SourceWidth); @@ -3255,10 +3431,10 @@ static HRESULT WINAPI BasicVideo_put_SourceWidth(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_get_SourceWidth(IBasicVideo2 *iface, - LONG *pSourceWidth) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_get_SourceWidth(IBasicVideo2 *iface, LONG *pSourceWidth) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, pSourceWidth); @@ -3275,10 +3451,10 @@ static HRESULT WINAPI BasicVideo_get_SourceWidth(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_put_SourceTop(IBasicVideo2 *iface, - LONG SourceTop) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_put_SourceTop(IBasicVideo2 *iface, LONG SourceTop) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%d)\n", This, iface, SourceTop); @@ -3295,10 +3471,10 @@ static HRESULT WINAPI BasicVideo_put_SourceTop(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_get_SourceTop(IBasicVideo2 *iface, - LONG *pSourceTop) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_get_SourceTop(IBasicVideo2 *iface, LONG *pSourceTop) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, pSourceTop); @@ -3315,10 +3491,10 @@ static HRESULT WINAPI BasicVideo_get_SourceTop(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_put_SourceHeight(IBasicVideo2 *iface, - LONG SourceHeight) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_put_SourceHeight(IBasicVideo2 *iface, LONG SourceHeight) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%d)\n", This, iface, SourceHeight); @@ -3335,10 +3511,10 @@ static HRESULT WINAPI BasicVideo_put_SourceHeight(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_get_SourceHeight(IBasicVideo2 *iface, - LONG *pSourceHeight) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_get_SourceHeight(IBasicVideo2 *iface, LONG *pSourceHeight) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, pSourceHeight); @@ -3355,10 +3531,10 @@ static HRESULT WINAPI BasicVideo_get_SourceHeight(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_put_DestinationLeft(IBasicVideo2 *iface, - LONG DestinationLeft) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_put_DestinationLeft(IBasicVideo2 *iface, LONG DestinationLeft) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%d)\n", This, iface, DestinationLeft); @@ -3375,10 +3551,10 @@ static HRESULT WINAPI BasicVideo_put_DestinationLeft(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_get_DestinationLeft(IBasicVideo2 *iface, - LONG *pDestinationLeft) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_get_DestinationLeft(IBasicVideo2 *iface, LONG *pDestinationLeft) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationLeft); @@ -3395,10 +3571,10 @@ static HRESULT WINAPI BasicVideo_get_DestinationLeft(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_put_DestinationWidth(IBasicVideo2 *iface, - LONG DestinationWidth) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_put_DestinationWidth(IBasicVideo2 *iface, LONG DestinationWidth) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%d)\n", This, iface, DestinationWidth); @@ -3415,10 +3591,10 @@ static HRESULT WINAPI BasicVideo_put_DestinationWidth(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_get_DestinationWidth(IBasicVideo2 *iface, - LONG *pDestinationWidth) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_get_DestinationWidth(IBasicVideo2 *iface, LONG *pDestinationWidth) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationWidth); @@ -3435,10 +3611,10 @@ static HRESULT WINAPI BasicVideo_get_DestinationWidth(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_put_DestinationTop(IBasicVideo2 *iface, - LONG DestinationTop) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_put_DestinationTop(IBasicVideo2 *iface, LONG DestinationTop) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%d)\n", This, iface, DestinationTop); @@ -3455,10 +3631,10 @@ static HRESULT WINAPI BasicVideo_put_DestinationTop(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_get_DestinationTop(IBasicVideo2 *iface, - LONG *pDestinationTop) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_get_DestinationTop(IBasicVideo2 *iface, LONG *pDestinationTop) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationTop); @@ -3475,10 +3651,10 @@ static HRESULT WINAPI BasicVideo_get_DestinationTop(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_put_DestinationHeight(IBasicVideo2 *iface, - LONG DestinationHeight) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_put_DestinationHeight(IBasicVideo2 *iface, LONG DestinationHeight) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%d)\n", This, iface, DestinationHeight); @@ -3496,9 +3672,10 @@ static HRESULT WINAPI BasicVideo_put_DestinationHeight(IBasicVideo2 *iface, } static HRESULT WINAPI BasicVideo_get_DestinationHeight(IBasicVideo2 *iface, - LONG *pDestinationHeight) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; + LONG *pDestinationHeight) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationHeight); @@ -3515,13 +3692,11 @@ static HRESULT WINAPI BasicVideo_get_DestinationHeight(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_SetSourcePosition(IBasicVideo2 *iface, - LONG Left, - LONG Top, - LONG Width, - LONG Height) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_SetSourcePosition(IBasicVideo2 *iface, LONG Left, LONG Top, + LONG Width, LONG Height) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height); @@ -3538,13 +3713,11 @@ static HRESULT WINAPI BasicVideo_SetSourcePosition(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_GetSourcePosition(IBasicVideo2 *iface, - LONG *pLeft, - LONG *pTop, - LONG *pWidth, - LONG *pHeight) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_GetSourcePosition(IBasicVideo2 *iface, LONG *pLeft, LONG *pTop, + LONG *pWidth, LONG *pHeight) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight); @@ -3561,9 +3734,10 @@ static HRESULT WINAPI BasicVideo_GetSourcePosition(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_SetDefaultSourcePosition(IBasicVideo2 *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_SetDefaultSourcePosition(IBasicVideo2 *iface) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->()\n", This, iface); @@ -3580,13 +3754,11 @@ static HRESULT WINAPI BasicVideo_SetDefaultSourcePosition(IBasicVideo2 *iface) { return hr; } -static HRESULT WINAPI BasicVideo_SetDestinationPosition(IBasicVideo2 *iface, - LONG Left, - LONG Top, - LONG Width, - LONG Height) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_SetDestinationPosition(IBasicVideo2 *iface, LONG Left, LONG Top, + LONG Width, LONG Height) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height); @@ -3603,13 +3775,11 @@ static HRESULT WINAPI BasicVideo_SetDestinationPosition(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_GetDestinationPosition(IBasicVideo2 *iface, - LONG *pLeft, - LONG *pTop, - LONG *pWidth, - LONG *pHeight) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_GetDestinationPosition(IBasicVideo2 *iface, LONG *pLeft, + LONG *pTop, LONG *pWidth, LONG *pHeight) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight); @@ -3626,9 +3796,10 @@ static HRESULT WINAPI BasicVideo_GetDestinationPosition(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_SetDefaultDestinationPosition(IBasicVideo2 *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_SetDefaultDestinationPosition(IBasicVideo2 *iface) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->()\n", This, iface); @@ -3645,11 +3816,10 @@ static HRESULT WINAPI BasicVideo_SetDefaultDestinationPosition(IBasicVideo2 *ifa return hr; } -static HRESULT WINAPI BasicVideo_GetVideoSize(IBasicVideo2 *iface, - LONG *pWidth, - LONG *pHeight) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_GetVideoSize(IBasicVideo2 *iface, LONG *pWidth, LONG *pHeight) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight); @@ -3666,13 +3836,11 @@ static HRESULT WINAPI BasicVideo_GetVideoSize(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_GetVideoPaletteEntries(IBasicVideo2 *iface, - LONG StartIndex, - LONG Entries, - LONG *pRetrieved, - LONG *pPalette) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_GetVideoPaletteEntries(IBasicVideo2 *iface, LONG StartIndex, + LONG Entries, LONG *pRetrieved, LONG *pPalette) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%d, %d, %p, %p)\n", This, iface, StartIndex, Entries, pRetrieved, pPalette); @@ -3689,11 +3857,11 @@ static HRESULT WINAPI BasicVideo_GetVideoPaletteEntries(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_GetCurrentImage(IBasicVideo2 *iface, - LONG *pBufferSize, - LONG *pDIBImage) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_GetCurrentImage(IBasicVideo2 *iface, LONG *pBufferSize, + LONG *pDIBImage) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->(%p, %p)\n", This, iface, pBufferSize, pDIBImage); @@ -3710,9 +3878,10 @@ static HRESULT WINAPI BasicVideo_GetCurrentImage(IBasicVideo2 *iface, return hr; } -static HRESULT WINAPI BasicVideo_IsUsingDefaultSource(IBasicVideo2 *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_IsUsingDefaultSource(IBasicVideo2 *iface) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->()\n", This, iface); @@ -3729,9 +3898,10 @@ static HRESULT WINAPI BasicVideo_IsUsingDefaultSource(IBasicVideo2 *iface) { return hr; } -static HRESULT WINAPI BasicVideo_IsUsingDefaultDestination(IBasicVideo2 *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); - IBasicVideo* pBasicVideo; +static HRESULT WINAPI BasicVideo_IsUsingDefaultDestination(IBasicVideo2 *iface) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); + IBasicVideo *pBasicVideo; HRESULT hr; TRACE("(%p/%p)->()\n", This, iface); @@ -3748,8 +3918,10 @@ static HRESULT WINAPI BasicVideo_IsUsingDefaultDestination(IBasicVideo2 *iface) return hr; } -static HRESULT WINAPI BasicVideo2_GetPreferredAspectRatio(IBasicVideo2 *iface, LONG *plAspectX, LONG *plAspectY) { - ICOM_THIS_MULTI(IFilterGraphImpl, IBasicVideo_vtbl, iface); +static HRESULT WINAPI BasicVideo2_GetPreferredAspectRatio(IBasicVideo2 *iface, LONG *plAspectX, + LONG *plAspectY) +{ + IFilterGraphImpl *This = impl_from_IBasicVideo2(iface); IBasicVideo2 *pBasicVideo2; HRESULT hr; @@ -3811,39 +3983,43 @@ static const IBasicVideo2Vtbl IBasicVideo_VTable = BasicVideo2_GetPreferredAspectRatio }; +static inline IFilterGraphImpl *impl_from_IVideoWindow(IVideoWindow *iface) +{ + return CONTAINING_RECORD(iface, IFilterGraphImpl, IVideoWindow_iface); +} -/*** IUnknown methods ***/ -static HRESULT WINAPI VideoWindow_QueryInterface(IVideoWindow *iface, - REFIID riid, - LPVOID*ppvObj) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); +static HRESULT WINAPI VideoWindow_QueryInterface(IVideoWindow *iface, REFIID riid, void **ppvObj) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); - return Filtergraph_QueryInterface(This, riid, ppvObj); + return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj); } -static ULONG WINAPI VideoWindow_AddRef(IVideoWindow *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); +static ULONG WINAPI VideoWindow_AddRef(IVideoWindow *iface) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); TRACE("(%p/%p)->()\n", This, iface); - return Filtergraph_AddRef(This); + return IUnknown_AddRef(This->outer_unk); } -static ULONG WINAPI VideoWindow_Release(IVideoWindow *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); +static ULONG WINAPI VideoWindow_Release(IVideoWindow *iface) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); TRACE("(%p/%p)->()\n", This, iface); - return Filtergraph_Release(This); + return IUnknown_Release(This->outer_unk); } /*** IDispatch methods ***/ -static HRESULT WINAPI VideoWindow_GetTypeInfoCount(IVideoWindow *iface, - UINT*pctinfo) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_GetTypeInfoCount(IVideoWindow *iface, UINT *pctinfo) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, pctinfo); @@ -3860,12 +4036,11 @@ static HRESULT WINAPI VideoWindow_GetTypeInfoCount(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_GetTypeInfo(IVideoWindow *iface, - UINT iTInfo, - LCID lcid, - ITypeInfo**ppTInfo) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_GetTypeInfo(IVideoWindow *iface, UINT iTInfo, LCID lcid, + ITypeInfo **ppTInfo) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%d, %d, %p)\n", This, iface, iTInfo, lcid, ppTInfo); @@ -3882,14 +4057,11 @@ static HRESULT WINAPI VideoWindow_GetTypeInfo(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_GetIDsOfNames(IVideoWindow *iface, - REFIID riid, - LPOLESTR*rgszNames, - UINT cNames, - LCID lcid, - DISPID*rgDispId) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_GetIDsOfNames(IVideoWindow *iface, REFIID riid, + LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p)\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId); @@ -3906,17 +4078,12 @@ static HRESULT WINAPI VideoWindow_GetIDsOfNames(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_Invoke(IVideoWindow *iface, - DISPID dispIdMember, - REFIID riid, - LCID lcid, - WORD wFlags, - DISPPARAMS*pDispParams, - VARIANT*pVarResult, - EXCEPINFO*pExepInfo, - UINT*puArgErr) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_Invoke(IVideoWindow *iface, DISPID dispIdMember, REFIID riid, + LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo, + UINT*puArgErr) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p)\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr); @@ -3935,12 +4102,12 @@ static HRESULT WINAPI VideoWindow_Invoke(IVideoWindow *iface, /*** IVideoWindow methods ***/ -static HRESULT WINAPI VideoWindow_put_Caption(IVideoWindow *iface, - BSTR strCaption) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_put_Caption(IVideoWindow *iface, BSTR strCaption) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; - + TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strCaption), strCaption); EnterCriticalSection(&This->cs); @@ -3955,10 +4122,10 @@ static HRESULT WINAPI VideoWindow_put_Caption(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_get_Caption(IVideoWindow *iface, - BSTR *strCaption) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_get_Caption(IVideoWindow *iface, BSTR *strCaption) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, strCaption); @@ -3975,10 +4142,10 @@ static HRESULT WINAPI VideoWindow_get_Caption(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_put_WindowStyle(IVideoWindow *iface, - LONG WindowStyle) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_put_WindowStyle(IVideoWindow *iface, LONG WindowStyle) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%d)\n", This, iface, WindowStyle); @@ -3995,10 +4162,10 @@ static HRESULT WINAPI VideoWindow_put_WindowStyle(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_get_WindowStyle(IVideoWindow *iface, - LONG *WindowStyle) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_get_WindowStyle(IVideoWindow *iface, LONG *WindowStyle) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyle); @@ -4015,10 +4182,10 @@ static HRESULT WINAPI VideoWindow_get_WindowStyle(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_put_WindowStyleEx(IVideoWindow *iface, - LONG WindowStyleEx) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_put_WindowStyleEx(IVideoWindow *iface, LONG WindowStyleEx) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%d)\n", This, iface, WindowStyleEx); @@ -4035,10 +4202,10 @@ static HRESULT WINAPI VideoWindow_put_WindowStyleEx(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_get_WindowStyleEx(IVideoWindow *iface, - LONG *WindowStyleEx) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_get_WindowStyleEx(IVideoWindow *iface, LONG *WindowStyleEx) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyleEx); @@ -4055,10 +4222,10 @@ static HRESULT WINAPI VideoWindow_get_WindowStyleEx(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_put_AutoShow(IVideoWindow *iface, - LONG AutoShow) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_put_AutoShow(IVideoWindow *iface, LONG AutoShow) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%d)\n", This, iface, AutoShow); @@ -4075,10 +4242,10 @@ static HRESULT WINAPI VideoWindow_put_AutoShow(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_get_AutoShow(IVideoWindow *iface, - LONG *AutoShow) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_get_AutoShow(IVideoWindow *iface, LONG *AutoShow) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, AutoShow); @@ -4095,10 +4262,10 @@ static HRESULT WINAPI VideoWindow_get_AutoShow(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_put_WindowState(IVideoWindow *iface, - LONG WindowState) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_put_WindowState(IVideoWindow *iface, LONG WindowState) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%d)\n", This, iface, WindowState); @@ -4115,10 +4282,10 @@ static HRESULT WINAPI VideoWindow_put_WindowState(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_get_WindowState(IVideoWindow *iface, - LONG *WindowState) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_get_WindowState(IVideoWindow *iface, LONG *WindowState) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, WindowState); @@ -4135,10 +4302,10 @@ static HRESULT WINAPI VideoWindow_get_WindowState(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_put_BackgroundPalette(IVideoWindow *iface, - LONG BackgroundPalette) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_put_BackgroundPalette(IVideoWindow *iface, LONG BackgroundPalette) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%d)\n", This, iface, BackgroundPalette); @@ -4156,9 +4323,10 @@ static HRESULT WINAPI VideoWindow_put_BackgroundPalette(IVideoWindow *iface, } static HRESULT WINAPI VideoWindow_get_BackgroundPalette(IVideoWindow *iface, - LONG *pBackgroundPalette) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; + LONG *pBackgroundPalette) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, pBackgroundPalette); @@ -4175,10 +4343,10 @@ static HRESULT WINAPI VideoWindow_get_BackgroundPalette(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_put_Visible(IVideoWindow *iface, - LONG Visible) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_put_Visible(IVideoWindow *iface, LONG Visible) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%d)\n", This, iface, Visible); @@ -4195,10 +4363,10 @@ static HRESULT WINAPI VideoWindow_put_Visible(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_get_Visible(IVideoWindow *iface, - LONG *pVisible) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_get_Visible(IVideoWindow *iface, LONG *pVisible) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, pVisible); @@ -4215,10 +4383,10 @@ static HRESULT WINAPI VideoWindow_get_Visible(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_put_Left(IVideoWindow *iface, - LONG Left) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_put_Left(IVideoWindow *iface, LONG Left) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%d)\n", This, iface, Left); @@ -4235,10 +4403,10 @@ static HRESULT WINAPI VideoWindow_put_Left(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_get_Left(IVideoWindow *iface, - LONG *pLeft) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_get_Left(IVideoWindow *iface, LONG *pLeft) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, pLeft); @@ -4255,10 +4423,10 @@ static HRESULT WINAPI VideoWindow_get_Left(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_put_Width(IVideoWindow *iface, - LONG Width) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_put_Width(IVideoWindow *iface, LONG Width) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%d)\n", This, iface, Width); @@ -4275,10 +4443,10 @@ static HRESULT WINAPI VideoWindow_put_Width(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_get_Width(IVideoWindow *iface, - LONG *pWidth) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_get_Width(IVideoWindow *iface, LONG *pWidth) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, pWidth); @@ -4295,10 +4463,10 @@ static HRESULT WINAPI VideoWindow_get_Width(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_put_Top(IVideoWindow *iface, - LONG Top) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_put_Top(IVideoWindow *iface, LONG Top) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%d)\n", This, iface, Top); @@ -4315,10 +4483,10 @@ static HRESULT WINAPI VideoWindow_put_Top(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_get_Top(IVideoWindow *iface, - LONG *pTop) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_get_Top(IVideoWindow *iface, LONG *pTop) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, pTop); @@ -4335,10 +4503,10 @@ static HRESULT WINAPI VideoWindow_get_Top(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_put_Height(IVideoWindow *iface, - LONG Height) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_put_Height(IVideoWindow *iface, LONG Height) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%d)\n", This, iface, Height); @@ -4355,10 +4523,10 @@ static HRESULT WINAPI VideoWindow_put_Height(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_get_Height(IVideoWindow *iface, - LONG *pHeight) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_get_Height(IVideoWindow *iface, LONG *pHeight) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, pHeight); @@ -4375,10 +4543,10 @@ static HRESULT WINAPI VideoWindow_get_Height(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_put_Owner(IVideoWindow *iface, - OAHWND Owner) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_put_Owner(IVideoWindow *iface, OAHWND Owner) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Owner); @@ -4395,10 +4563,10 @@ static HRESULT WINAPI VideoWindow_put_Owner(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_get_Owner(IVideoWindow *iface, - OAHWND *Owner) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_get_Owner(IVideoWindow *iface, OAHWND *Owner) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, Owner); @@ -4415,10 +4583,10 @@ static HRESULT WINAPI VideoWindow_get_Owner(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_put_MessageDrain(IVideoWindow *iface, - OAHWND Drain) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_put_MessageDrain(IVideoWindow *iface, OAHWND Drain) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Drain); @@ -4435,10 +4603,10 @@ static HRESULT WINAPI VideoWindow_put_MessageDrain(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_get_MessageDrain(IVideoWindow *iface, - OAHWND *Drain) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_get_MessageDrain(IVideoWindow *iface, OAHWND *Drain) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, Drain); @@ -4455,10 +4623,10 @@ static HRESULT WINAPI VideoWindow_get_MessageDrain(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_get_BorderColor(IVideoWindow *iface, - LONG *Color) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_get_BorderColor(IVideoWindow *iface, LONG *Color) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, Color); @@ -4475,10 +4643,10 @@ static HRESULT WINAPI VideoWindow_get_BorderColor(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_put_BorderColor(IVideoWindow *iface, - LONG Color) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_put_BorderColor(IVideoWindow *iface, LONG Color) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%d)\n", This, iface, Color); @@ -4495,10 +4663,10 @@ static HRESULT WINAPI VideoWindow_put_BorderColor(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_get_FullScreenMode(IVideoWindow *iface, - LONG *FullScreenMode) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_get_FullScreenMode(IVideoWindow *iface, LONG *FullScreenMode) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, FullScreenMode); @@ -4515,10 +4683,10 @@ static HRESULT WINAPI VideoWindow_get_FullScreenMode(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_put_FullScreenMode(IVideoWindow *iface, - LONG FullScreenMode) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_put_FullScreenMode(IVideoWindow *iface, LONG FullScreenMode) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%d)\n", This, iface, FullScreenMode); @@ -4535,10 +4703,10 @@ static HRESULT WINAPI VideoWindow_put_FullScreenMode(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_SetWindowForeground(IVideoWindow *iface, - LONG Focus) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_SetWindowForeground(IVideoWindow *iface, LONG Focus) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%d)\n", This, iface, Focus); @@ -4555,13 +4723,11 @@ static HRESULT WINAPI VideoWindow_SetWindowForeground(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_NotifyOwnerMessage(IVideoWindow *iface, - OAHWND hwnd, - LONG uMsg, - LONG_PTR wParam, - LONG_PTR lParam) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_NotifyOwnerMessage(IVideoWindow *iface, OAHWND hwnd, LONG uMsg, + LONG_PTR wParam, LONG_PTR lParam) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%08lx, %d, %08lx, %08lx)\n", This, iface, hwnd, uMsg, wParam, lParam); @@ -4578,13 +4744,11 @@ static HRESULT WINAPI VideoWindow_NotifyOwnerMessage(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_SetWindowPosition(IVideoWindow *iface, - LONG Left, - LONG Top, - LONG Width, - LONG Height) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_SetWindowPosition(IVideoWindow *iface, LONG Left, LONG Top, + LONG Width, LONG Height) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height); @@ -4601,13 +4765,11 @@ static HRESULT WINAPI VideoWindow_SetWindowPosition(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_GetWindowPosition(IVideoWindow *iface, - LONG *pLeft, - LONG *pTop, - LONG *pWidth, - LONG *pHeight) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_GetWindowPosition(IVideoWindow *iface, LONG *pLeft, LONG *pTop, + LONG *pWidth, LONG *pHeight) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight); @@ -4624,11 +4786,11 @@ static HRESULT WINAPI VideoWindow_GetWindowPosition(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_GetMinIdealImageSize(IVideoWindow *iface, - LONG *pWidth, - LONG *pHeight) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_GetMinIdealImageSize(IVideoWindow *iface, LONG *pWidth, + LONG *pHeight) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight); @@ -4645,11 +4807,11 @@ static HRESULT WINAPI VideoWindow_GetMinIdealImageSize(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_GetMaxIdealImageSize(IVideoWindow *iface, - LONG *pWidth, - LONG *pHeight) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_GetMaxIdealImageSize(IVideoWindow *iface, LONG *pWidth, + LONG *pHeight) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight); @@ -4666,13 +4828,11 @@ static HRESULT WINAPI VideoWindow_GetMaxIdealImageSize(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_GetRestorePosition(IVideoWindow *iface, - LONG *pLeft, - LONG *pTop, - LONG *pWidth, - LONG *pHeight) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_GetRestorePosition(IVideoWindow *iface, LONG *pLeft, LONG *pTop, + LONG *pWidth, LONG *pHeight) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight); @@ -4689,10 +4849,10 @@ static HRESULT WINAPI VideoWindow_GetRestorePosition(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_HideCursor(IVideoWindow *iface, - LONG HideCursor) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_HideCursor(IVideoWindow *iface, LONG HideCursor) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%d)\n", This, iface, HideCursor); @@ -4709,10 +4869,10 @@ static HRESULT WINAPI VideoWindow_HideCursor(IVideoWindow *iface, return hr; } -static HRESULT WINAPI VideoWindow_IsCursorHidden(IVideoWindow *iface, - LONG *CursorHidden) { - ICOM_THIS_MULTI(IFilterGraphImpl, IVideoWindow_vtbl, iface); - IVideoWindow* pVideoWindow; +static HRESULT WINAPI VideoWindow_IsCursorHidden(IVideoWindow *iface, LONG *CursorHidden) +{ + IFilterGraphImpl *This = impl_from_IVideoWindow(iface); + IVideoWindow *pVideoWindow; HRESULT hr; TRACE("(%p/%p)->(%p)\n", This, iface, CursorHidden); @@ -4780,78 +4940,73 @@ static const IVideoWindowVtbl IVideoWindow_VTable = VideoWindow_IsCursorHidden }; +static inline IFilterGraphImpl *impl_from_IMediaEventEx(IMediaEventEx *iface) +{ + return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaEventEx_iface); +} -/*** IUnknown methods ***/ -static HRESULT WINAPI MediaEvent_QueryInterface(IMediaEventEx *iface, - REFIID riid, - LPVOID*ppvObj) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); +static HRESULT WINAPI MediaEvent_QueryInterface(IMediaEventEx *iface, REFIID riid, void **ppvObj) +{ + IFilterGraphImpl *This = impl_from_IMediaEventEx(iface); TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); - return Filtergraph_QueryInterface(This, riid, ppvObj); + return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj); } -static ULONG WINAPI MediaEvent_AddRef(IMediaEventEx *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); +static ULONG WINAPI MediaEvent_AddRef(IMediaEventEx *iface) +{ + IFilterGraphImpl *This = impl_from_IMediaEventEx(iface); TRACE("(%p/%p)->()\n", This, iface); - return Filtergraph_AddRef(This); + return IUnknown_AddRef(This->outer_unk); } -static ULONG WINAPI MediaEvent_Release(IMediaEventEx *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); +static ULONG WINAPI MediaEvent_Release(IMediaEventEx *iface) +{ + IFilterGraphImpl *This = impl_from_IMediaEventEx(iface); TRACE("(%p/%p)->()\n", This, iface); - return Filtergraph_Release(This); + return IUnknown_Release(This->outer_unk); } /*** IDispatch methods ***/ -static HRESULT WINAPI MediaEvent_GetTypeInfoCount(IMediaEventEx *iface, - UINT*pctinfo) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); +static HRESULT WINAPI MediaEvent_GetTypeInfoCount(IMediaEventEx *iface, UINT *pctinfo) +{ + IFilterGraphImpl *This = impl_from_IMediaEventEx(iface); TRACE("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo); return S_OK; } -static HRESULT WINAPI MediaEvent_GetTypeInfo(IMediaEventEx *iface, - UINT iTInfo, - LCID lcid, - ITypeInfo**ppTInfo) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); +static HRESULT WINAPI MediaEvent_GetTypeInfo(IMediaEventEx *iface, UINT iTInfo, LCID lcid, + ITypeInfo **ppTInfo) +{ + IFilterGraphImpl *This = impl_from_IMediaEventEx(iface); TRACE("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo); return S_OK; } -static HRESULT WINAPI MediaEvent_GetIDsOfNames(IMediaEventEx *iface, - REFIID riid, - LPOLESTR*rgszNames, - UINT cNames, - LCID lcid, - DISPID*rgDispId) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); +static HRESULT WINAPI MediaEvent_GetIDsOfNames(IMediaEventEx *iface, REFIID riid, + LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) +{ + IFilterGraphImpl *This = impl_from_IMediaEventEx(iface); TRACE("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId); return S_OK; } -static HRESULT WINAPI MediaEvent_Invoke(IMediaEventEx *iface, - DISPID dispIdMember, - REFIID riid, - LCID lcid, - WORD wFlags, - DISPPARAMS*pDispParams, - VARIANT*pVarResult, - EXCEPINFO*pExepInfo, - UINT*puArgErr) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); +static HRESULT WINAPI MediaEvent_Invoke(IMediaEventEx *iface, DISPID dispIdMember, REFIID riid, + LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo, + UINT *puArgErr) +{ + IFilterGraphImpl *This = impl_from_IMediaEventEx(iface); TRACE("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr); @@ -4859,9 +5014,9 @@ static HRESULT WINAPI MediaEvent_Invoke(IMediaEventEx *iface, } /*** IMediaEvent methods ***/ -static HRESULT WINAPI MediaEvent_GetEventHandle(IMediaEventEx *iface, - OAEVENT *hEvent) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); +static HRESULT WINAPI MediaEvent_GetEventHandle(IMediaEventEx *iface, OAEVENT *hEvent) +{ + IFilterGraphImpl *This = impl_from_IMediaEventEx(iface); TRACE("(%p/%p)->(%p)\n", This, iface, hEvent); @@ -4870,12 +5025,10 @@ static HRESULT WINAPI MediaEvent_GetEventHandle(IMediaEventEx *iface, return S_OK; } -static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface, - LONG *lEventCode, - LONG_PTR *lParam1, - LONG_PTR *lParam2, - LONG msTimeout) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); +static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface, LONG *lEventCode, LONG_PTR *lParam1, + LONG_PTR *lParam2, LONG msTimeout) +{ + IFilterGraphImpl *This = impl_from_IMediaEventEx(iface); Event evt; TRACE("(%p/%p)->(%p, %p, %p, %d)\n", This, iface, lEventCode, lParam1, lParam2, msTimeout); @@ -4892,10 +5045,10 @@ static HRESULT WINAPI MediaEvent_GetEvent(IMediaEventEx *iface, return E_ABORT; } -static HRESULT WINAPI MediaEvent_WaitForCompletion(IMediaEventEx *iface, - LONG msTimeout, - LONG *pEvCode) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); +static HRESULT WINAPI MediaEvent_WaitForCompletion(IMediaEventEx *iface, LONG msTimeout, + LONG *pEvCode) +{ + IFilterGraphImpl *This = impl_from_IMediaEventEx(iface); TRACE("(%p/%p)->(%d, %p)\n", This, iface, msTimeout, pEvCode); @@ -4912,9 +5065,9 @@ static HRESULT WINAPI MediaEvent_WaitForCompletion(IMediaEventEx *iface, return E_ABORT; } -static HRESULT WINAPI MediaEvent_CancelDefaultHandling(IMediaEventEx *iface, - LONG lEvCode) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); +static HRESULT WINAPI MediaEvent_CancelDefaultHandling(IMediaEventEx *iface, LONG lEvCode) +{ + IFilterGraphImpl *This = impl_from_IMediaEventEx(iface); TRACE("(%p/%p)->(%d)\n", This, iface, lEvCode); @@ -4930,9 +5083,9 @@ static HRESULT WINAPI MediaEvent_CancelDefaultHandling(IMediaEventEx *iface, return S_OK; } -static HRESULT WINAPI MediaEvent_RestoreDefaultHandling(IMediaEventEx *iface, - LONG lEvCode) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); +static HRESULT WINAPI MediaEvent_RestoreDefaultHandling(IMediaEventEx *iface, LONG lEvCode) +{ + IFilterGraphImpl *This = impl_from_IMediaEventEx(iface); TRACE("(%p/%p)->(%d)\n", This, iface, lEvCode); @@ -4948,11 +5101,10 @@ static HRESULT WINAPI MediaEvent_RestoreDefaultHandling(IMediaEventEx *iface, return S_OK; } -static HRESULT WINAPI MediaEvent_FreeEventParams(IMediaEventEx *iface, - LONG lEvCode, - LONG_PTR lParam1, - LONG_PTR lParam2) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); +static HRESULT WINAPI MediaEvent_FreeEventParams(IMediaEventEx *iface, LONG lEvCode, + LONG_PTR lParam1, LONG_PTR lParam2) +{ + IFilterGraphImpl *This = impl_from_IMediaEventEx(iface); TRACE("(%p/%p)->(%d, %08lx, %08lx): stub !!!\n", This, iface, lEvCode, lParam1, lParam2); @@ -4960,11 +5112,10 @@ static HRESULT WINAPI MediaEvent_FreeEventParams(IMediaEventEx *iface, } /*** IMediaEventEx methods ***/ -static HRESULT WINAPI MediaEvent_SetNotifyWindow(IMediaEventEx *iface, - OAHWND hwnd, - LONG lMsg, - LONG_PTR lInstanceData) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); +static HRESULT WINAPI MediaEvent_SetNotifyWindow(IMediaEventEx *iface, OAHWND hwnd, LONG lMsg, + LONG_PTR lInstanceData) +{ + IFilterGraphImpl *This = impl_from_IMediaEventEx(iface); TRACE("(%p/%p)->(%08lx, %d, %08lx)\n", This, iface, hwnd, lMsg, lInstanceData); @@ -4975,9 +5126,9 @@ static HRESULT WINAPI MediaEvent_SetNotifyWindow(IMediaEventEx *iface, return S_OK; } -static HRESULT WINAPI MediaEvent_SetNotifyFlags(IMediaEventEx *iface, - LONG lNoNotifyFlags) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); +static HRESULT WINAPI MediaEvent_SetNotifyFlags(IMediaEventEx *iface, LONG lNoNotifyFlags) +{ + IFilterGraphImpl *This = impl_from_IMediaEventEx(iface); TRACE("(%p/%p)->(%d)\n", This, iface, lNoNotifyFlags); @@ -4989,9 +5140,9 @@ static HRESULT WINAPI MediaEvent_SetNotifyFlags(IMediaEventEx *iface, return S_OK; } -static HRESULT WINAPI MediaEvent_GetNotifyFlags(IMediaEventEx *iface, - LONG *lplNoNotifyFlags) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventEx_vtbl, iface); +static HRESULT WINAPI MediaEvent_GetNotifyFlags(IMediaEventEx *iface, LONG *lplNoNotifyFlags) +{ + IFilterGraphImpl *This = impl_from_IMediaEventEx(iface); TRACE("(%p/%p)->(%p)\n", This, iface, lplNoNotifyFlags); @@ -5025,25 +5176,30 @@ static const IMediaEventExVtbl IMediaEventEx_VTable = }; -static HRESULT WINAPI MediaFilter_QueryInterface(IMediaFilter *iface, REFIID riid, LPVOID *ppv) +static inline IFilterGraphImpl *impl_from_IMediaFilter(IMediaFilter *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface); + return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaFilter_iface); +} - return Filtergraph_QueryInterface(This, riid, ppv); +static HRESULT WINAPI MediaFilter_QueryInterface(IMediaFilter *iface, REFIID riid, void **ppv) +{ + IFilterGraphImpl *This = impl_from_IMediaFilter(iface); + + return IUnknown_QueryInterface(This->outer_unk, riid, ppv); } static ULONG WINAPI MediaFilter_AddRef(IMediaFilter *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface); + IFilterGraphImpl *This = impl_from_IMediaFilter(iface); - return Filtergraph_AddRef(This); + return IUnknown_AddRef(This->outer_unk); } static ULONG WINAPI MediaFilter_Release(IMediaFilter *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface); + IFilterGraphImpl *This = impl_from_IMediaFilter(iface); - return Filtergraph_Release(This); + return IUnknown_Release(This->outer_unk); } static HRESULT WINAPI MediaFilter_GetClassID(IMediaFilter *iface, CLSID * pClassID) @@ -5055,31 +5211,40 @@ static HRESULT WINAPI MediaFilter_GetClassID(IMediaFilter *iface, CLSID * pClass static HRESULT WINAPI MediaFilter_Stop(IMediaFilter *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface); - return MediaControl_Stop((IMediaControl*)&This->IMediaControl_vtbl); + IFilterGraphImpl *This = impl_from_IMediaFilter(iface); + + return MediaControl_Stop(&This->IMediaControl_iface); } static HRESULT WINAPI MediaFilter_Pause(IMediaFilter *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface); - return MediaControl_Pause((IMediaControl*)&This->IMediaControl_vtbl); + IFilterGraphImpl *This = impl_from_IMediaFilter(iface); + + return MediaControl_Pause(&This->IMediaControl_iface); } static HRESULT WINAPI MediaFilter_Run(IMediaFilter *iface, REFERENCE_TIME tStart) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface); - return MediaControl_Run((IMediaControl*)&This->IMediaControl_vtbl); + IFilterGraphImpl *This = impl_from_IMediaFilter(iface); + + if (tStart) + FIXME("Run called with non-null tStart: %x%08x\n", + (int)(tStart>>32), (int)tStart); + + return MediaControl_Run(&This->IMediaControl_iface); } -static HRESULT WINAPI MediaFilter_GetState(IMediaFilter *iface, DWORD dwMsTimeout, FILTER_STATE * pState) +static HRESULT WINAPI MediaFilter_GetState(IMediaFilter *iface, DWORD dwMsTimeout, + FILTER_STATE *pState) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface); - return MediaControl_GetState((IMediaControl*)&This->IMediaControl_vtbl, dwMsTimeout, (OAFilterState*)pState); + IFilterGraphImpl *This = impl_from_IMediaFilter(iface); + + return MediaControl_GetState(&This->IMediaControl_iface, dwMsTimeout, (OAFilterState*)pState); } static HRESULT WINAPI MediaFilter_SetSyncSource(IMediaFilter *iface, IReferenceClock *pClock) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface); + IFilterGraphImpl *This = impl_from_IMediaFilter(iface); HRESULT hr = S_OK; int i; @@ -5106,6 +5271,7 @@ static HRESULT WINAPI MediaFilter_SetSyncSource(IMediaFilter *iface, IReferenceC This->refClock = pClock; if (This->refClock) IReferenceClock_AddRef(This->refClock); + This->defaultclock = FALSE; if (This->HandleEcClockChanged) { @@ -5128,7 +5294,7 @@ static HRESULT WINAPI MediaFilter_SetSyncSource(IMediaFilter *iface, IReferenceC static HRESULT WINAPI MediaFilter_GetSyncSource(IMediaFilter *iface, IReferenceClock **ppClock) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaFilter_vtbl, iface); + IFilterGraphImpl *This = impl_from_IMediaFilter(iface); TRACE("(%p/%p)->(%p)\n", iface, This, ppClock); @@ -5160,30 +5326,36 @@ static const IMediaFilterVtbl IMediaFilter_VTable = MediaFilter_GetSyncSource }; -static HRESULT WINAPI MediaEventSink_QueryInterface(IMediaEventSink *iface, REFIID riid, LPVOID *ppv) +static inline IFilterGraphImpl *impl_from_IMediaEventSink(IMediaEventSink *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface); + return CONTAINING_RECORD(iface, IFilterGraphImpl, IMediaEventSink_iface); +} - return Filtergraph_QueryInterface(This, riid, ppv); +static HRESULT WINAPI MediaEventSink_QueryInterface(IMediaEventSink *iface, REFIID riid, void **ppv) +{ + IFilterGraphImpl *This = impl_from_IMediaEventSink(iface); + + return IUnknown_QueryInterface(This->outer_unk, riid, ppv); } static ULONG WINAPI MediaEventSink_AddRef(IMediaEventSink *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface); + IFilterGraphImpl *This = impl_from_IMediaEventSink(iface); - return Filtergraph_AddRef(This); + return IUnknown_AddRef(This->outer_unk); } static ULONG WINAPI MediaEventSink_Release(IMediaEventSink *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface); + IFilterGraphImpl *This = impl_from_IMediaEventSink(iface); - return Filtergraph_Release(This); + return IUnknown_Release(This->outer_unk); } -static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, LONG EventCode, LONG_PTR EventParam1, LONG_PTR EventParam2) +static HRESULT WINAPI MediaEventSink_Notify(IMediaEventSink *iface, LONG EventCode, + LONG_PTR EventParam1, LONG_PTR EventParam2) { - ICOM_THIS_MULTI(IFilterGraphImpl, IMediaEventSink_vtbl, iface); + IFilterGraphImpl *This = impl_from_IMediaEventSink(iface); Event evt; TRACE("(%p/%p)->(%d, %ld, %ld)\n", This, iface, EventCode, EventParam1, EventParam2); @@ -5236,49 +5408,47 @@ static const IMediaEventSinkVtbl IMediaEventSink_VTable = MediaEventSink_Notify }; -static HRESULT WINAPI GraphConfig_QueryInterface(IGraphConfig *iface, REFIID riid, LPVOID *ppv) +static inline IFilterGraphImpl *impl_from_IGraphConfig(IGraphConfig *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); + return CONTAINING_RECORD(iface, IFilterGraphImpl, IGraphConfig_iface); +} - return Filtergraph_QueryInterface(This, riid, ppv); +static HRESULT WINAPI GraphConfig_QueryInterface(IGraphConfig *iface, REFIID riid, void **ppv) +{ + IFilterGraphImpl *This = impl_from_IGraphConfig(iface); + + return IUnknown_QueryInterface(This->outer_unk, riid, ppv); } static ULONG WINAPI GraphConfig_AddRef(IGraphConfig *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); + IFilterGraphImpl *This = impl_from_IGraphConfig(iface); - return Filtergraph_AddRef(This); + return IUnknown_AddRef(This->outer_unk); } static ULONG WINAPI GraphConfig_Release(IGraphConfig *iface) { - ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); + IFilterGraphImpl *This = impl_from_IGraphConfig(iface); - return Filtergraph_Release(This); + return IUnknown_Release(This->outer_unk); } -static HRESULT WINAPI GraphConfig_Reconnect(IGraphConfig *iface, - IPin* pOutputPin, - IPin* pInputPin, - const AM_MEDIA_TYPE* pmtFirstConnection, - IBaseFilter* pUsingFilter, - HANDLE hAbortEvent, - DWORD dwFlags) +static HRESULT WINAPI GraphConfig_Reconnect(IGraphConfig *iface, IPin *pOutputPin, IPin *pInputPin, + const AM_MEDIA_TYPE *pmtFirstConnection, IBaseFilter *pUsingFilter, HANDLE hAbortEvent, + DWORD dwFlags) { - ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); + IFilterGraphImpl *This = impl_from_IGraphConfig(iface); FIXME("(%p)->(%p, %p, %p, %p, %p, %x): stub!\n", This, pOutputPin, pInputPin, pmtFirstConnection, pUsingFilter, hAbortEvent, dwFlags); return E_NOTIMPL; } -static HRESULT WINAPI GraphConfig_Reconfigure(IGraphConfig *iface, - IGraphConfigCallback* pCallback, - PVOID pvContext, - DWORD dwFlags, - HANDLE hAbortEvent) +static HRESULT WINAPI GraphConfig_Reconfigure(IGraphConfig *iface, IGraphConfigCallback *pCallback, + void *pvContext, DWORD dwFlags, HANDLE hAbortEvent) { - ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); + IFilterGraphImpl *This = impl_from_IGraphConfig(iface); HRESULT hr; WARN("(%p)->(%p, %p, %x, %p): partial stub!\n", This, pCallback, pvContext, dwFlags, hAbortEvent); @@ -5295,88 +5465,79 @@ static HRESULT WINAPI GraphConfig_Reconfigure(IGraphConfig *iface, return hr; } -static HRESULT WINAPI GraphConfig_AddFilterToCache(IGraphConfig *iface, - IBaseFilter* pFilter) +static HRESULT WINAPI GraphConfig_AddFilterToCache(IGraphConfig *iface, IBaseFilter *pFilter) { - ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); + IFilterGraphImpl *This = impl_from_IGraphConfig(iface); FIXME("(%p)->(%p): stub!\n", This, pFilter); - + return E_NOTIMPL; } -static HRESULT WINAPI GraphConfig_EnumCacheFilter(IGraphConfig *iface, - IEnumFilters** pEnum) +static HRESULT WINAPI GraphConfig_EnumCacheFilter(IGraphConfig *iface, IEnumFilters **pEnum) { - ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); + IFilterGraphImpl *This = impl_from_IGraphConfig(iface); FIXME("(%p)->(%p): stub!\n", This, pEnum); - + return E_NOTIMPL; } -static HRESULT WINAPI GraphConfig_RemoveFilterFromCache(IGraphConfig *iface, - IBaseFilter* pFilter) +static HRESULT WINAPI GraphConfig_RemoveFilterFromCache(IGraphConfig *iface, IBaseFilter *pFilter) { - ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); + IFilterGraphImpl *This = impl_from_IGraphConfig(iface); FIXME("(%p)->(%p): stub!\n", This, pFilter); - + return E_NOTIMPL; } -static HRESULT WINAPI GraphConfig_GetStartTime(IGraphConfig *iface, - REFERENCE_TIME* prtStart) +static HRESULT WINAPI GraphConfig_GetStartTime(IGraphConfig *iface, REFERENCE_TIME *prtStart) { - ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); + IFilterGraphImpl *This = impl_from_IGraphConfig(iface); FIXME("(%p)->(%p): stub!\n", This, prtStart); - + return E_NOTIMPL; } -static HRESULT WINAPI GraphConfig_PushThroughData(IGraphConfig *iface, - IPin* pOutputPin, - IPinConnection* pConnection, - HANDLE hEventAbort) +static HRESULT WINAPI GraphConfig_PushThroughData(IGraphConfig *iface, IPin *pOutputPin, + IPinConnection *pConnection, HANDLE hEventAbort) { - ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); + IFilterGraphImpl *This = impl_from_IGraphConfig(iface); FIXME("(%p)->(%p, %p, %p): stub!\n", This, pOutputPin, pConnection, hEventAbort); - + return E_NOTIMPL; } -static HRESULT WINAPI GraphConfig_SetFilterFlags(IGraphConfig *iface, - IBaseFilter* pFilter, - DWORD dwFlags) +static HRESULT WINAPI GraphConfig_SetFilterFlags(IGraphConfig *iface, IBaseFilter *pFilter, + DWORD dwFlags) { - ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); + IFilterGraphImpl *This = impl_from_IGraphConfig(iface); FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags); - + return E_NOTIMPL; } -static HRESULT WINAPI GraphConfig_GetFilterFlags(IGraphConfig *iface, - IBaseFilter* pFilter, - DWORD* dwFlags) +static HRESULT WINAPI GraphConfig_GetFilterFlags(IGraphConfig *iface, IBaseFilter *pFilter, + DWORD *dwFlags) { - ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); + IFilterGraphImpl *This = impl_from_IGraphConfig(iface); FIXME("(%p)->(%p, %p): stub!\n", This, pFilter, dwFlags); - + return E_NOTIMPL; } -static HRESULT WINAPI GraphConfig_RemoveFilterEx(IGraphConfig *iface, - IBaseFilter* pFilter, - DWORD dwFlags) +static HRESULT WINAPI GraphConfig_RemoveFilterEx(IGraphConfig *iface, IBaseFilter *pFilter, + DWORD dwFlags) { - ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface); + IFilterGraphImpl *This = impl_from_IGraphConfig(iface); FIXME("(%p)->(%p, %x): stub!\n", This, pFilter, dwFlags); - + return E_NOTIMPL; } @@ -5397,6 +5558,53 @@ static const IGraphConfigVtbl IGraphConfig_VTable = GraphConfig_RemoveFilterEx }; +static inline IFilterGraphImpl *impl_from_IGraphVersion(IGraphVersion *iface) +{ + return CONTAINING_RECORD(iface, IFilterGraphImpl, IGraphVersion_iface); +} + +static HRESULT WINAPI GraphVersion_QueryInterface(IGraphVersion *iface, REFIID riid, void **ppv) +{ + IFilterGraphImpl *This = impl_from_IGraphVersion(iface); + + return IUnknown_QueryInterface(This->outer_unk, riid, ppv); +} + +static ULONG WINAPI GraphVersion_AddRef(IGraphVersion *iface) +{ + IFilterGraphImpl *This = impl_from_IGraphVersion(iface); + + return IUnknown_AddRef(This->outer_unk); +} + +static ULONG WINAPI GraphVersion_Release(IGraphVersion *iface) +{ + IFilterGraphImpl *This = impl_from_IGraphVersion(iface); + + return IUnknown_Release(This->outer_unk); +} + +static HRESULT WINAPI GraphVersion_QueryVersion(IGraphVersion *iface, LONG *pVersion) +{ + IFilterGraphImpl *This = impl_from_IGraphVersion(iface); + + if(!pVersion) + return E_POINTER; + + TRACE("(%p)->(%p): current version %i\n", This, pVersion, This->version); + + *pVersion = This->version; + return S_OK; +} + +static const IGraphVersionVtbl IGraphVersion_VTable = +{ + GraphVersion_QueryInterface, + GraphVersion_AddRef, + GraphVersion_Release, + GraphVersion_QueryVersion, +}; + static const IUnknownVtbl IInner_VTable = { FilterGraphInner_QueryInterface, @@ -5404,47 +5612,6 @@ static const IUnknownVtbl IInner_VTable = FilterGraphInner_Release }; -static HRESULT Filtergraph_QueryInterface(IFilterGraphImpl *This, - REFIID riid, - LPVOID * ppv) { - if (This->bAggregatable) - This->bUnkOuterValid = TRUE; - - if (This->pUnkOuter) - { - if (This->bAggregatable) - return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv); - - if (IsEqualIID(riid, &IID_IUnknown)) - { - HRESULT hr; - - IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl)); - hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv); - IUnknown_Release((IUnknown *)&(This->IInner_vtbl)); - This->bAggregatable = TRUE; - return hr; - } - - *ppv = NULL; - return E_NOINTERFACE; - } - - return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv); -} - -static ULONG Filtergraph_AddRef(IFilterGraphImpl *This) { - if (This->pUnkOuter && This->bUnkOuterValid) - return IUnknown_AddRef(This->pUnkOuter); - return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl)); -} - -static ULONG Filtergraph_Release(IFilterGraphImpl *This) { - if (This->pUnkOuter && This->bUnkOuterValid) - return IUnknown_Release(This->pUnkOuter); - return IUnknown_Release((IUnknown *)&(This->IInner_vtbl)); -} - /* This is the only function that actually creates a FilterGraph class... */ HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj) { @@ -5456,21 +5623,21 @@ HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj) *ppObj = NULL; fimpl = CoTaskMemAlloc(sizeof(*fimpl)); - fimpl->pUnkOuter = pUnkOuter; - fimpl->bUnkOuterValid = FALSE; - fimpl->bAggregatable = FALSE; - fimpl->IInner_vtbl = &IInner_VTable; - fimpl->IFilterGraph2_vtbl = &IFilterGraph2_VTable; - fimpl->IMediaControl_vtbl = &IMediaControl_VTable; - fimpl->IMediaSeeking_vtbl = &IMediaSeeking_VTable; - fimpl->IBasicAudio_vtbl = &IBasicAudio_VTable; - fimpl->IBasicVideo_vtbl = &IBasicVideo_VTable; - fimpl->IVideoWindow_vtbl = &IVideoWindow_VTable; - fimpl->IMediaEventEx_vtbl = &IMediaEventEx_VTable; - fimpl->IMediaFilter_vtbl = &IMediaFilter_VTable; - fimpl->IMediaEventSink_vtbl = &IMediaEventSink_VTable; - fimpl->IGraphConfig_vtbl = &IGraphConfig_VTable; - fimpl->IMediaPosition_vtbl = &IMediaPosition_VTable; + fimpl->defaultclock = TRUE; + fimpl->IUnknown_inner.lpVtbl = &IInner_VTable; + fimpl->IFilterGraph2_iface.lpVtbl = &IFilterGraph2_VTable; + fimpl->IMediaControl_iface.lpVtbl = &IMediaControl_VTable; + fimpl->IMediaSeeking_iface.lpVtbl = &IMediaSeeking_VTable; + fimpl->IBasicAudio_iface.lpVtbl = &IBasicAudio_VTable; + fimpl->IBasicVideo2_iface.lpVtbl = &IBasicVideo_VTable; + fimpl->IVideoWindow_iface.lpVtbl = &IVideoWindow_VTable; + fimpl->IMediaEventEx_iface.lpVtbl = &IMediaEventEx_VTable; + fimpl->IMediaFilter_iface.lpVtbl = &IMediaFilter_VTable; + fimpl->IMediaEventSink_iface.lpVtbl = &IMediaEventSink_VTable; + fimpl->IGraphConfig_iface.lpVtbl = &IGraphConfig_VTable; + fimpl->IMediaPosition_iface.lpVtbl = &IMediaPosition_VTable; + fimpl->IObjectWithSite_iface.lpVtbl = &IObjectWithSite_VTable; + fimpl->IGraphVersion_iface.lpVtbl = &IGraphVersion_VTable; fimpl->ref = 1; fimpl->ppFiltersInGraph = NULL; fimpl->pFilterNames = NULL; @@ -5486,30 +5653,36 @@ HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj) fimpl->notif.disabled = FALSE; fimpl->nRenderers = 0; fimpl->EcCompleteCount = 0; + fimpl->refClockProvider = NULL; fimpl->state = State_Stopped; + fimpl->pSite = NULL; EventsQueue_Init(&fimpl->evqueue); InitializeCriticalSection(&fimpl->cs); fimpl->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IFilterGraphImpl.cs"); fimpl->nItfCacheEntries = 0; memcpy(&fimpl->timeformatseek, &TIME_FORMAT_MEDIA_TIME, sizeof(GUID)); - fimpl->start_time = fimpl->position = 0; + fimpl->start_time = fimpl->pause_time = 0; fimpl->stop_position = -1; fimpl->punkFilterMapper2 = NULL; fimpl->recursioncount = 0; + fimpl->version = 0; + + if (pUnkOuter) + fimpl->outer_unk = pUnkOuter; + else + fimpl->outer_unk = &fimpl->IUnknown_inner; /* create Filtermapper aggregated. */ - hr = CoCreateInstance(&CLSID_FilterMapper2, pUnkOuter ? pUnkOuter : (IUnknown*)&fimpl->IInner_vtbl, CLSCTX_INPROC_SERVER, - &IID_IUnknown, (LPVOID*)&fimpl->punkFilterMapper2); + hr = CoCreateInstance(&CLSID_FilterMapper2, fimpl->outer_unk, CLSCTX_INPROC_SERVER, + &IID_IUnknown, (void**)&fimpl->punkFilterMapper2); - if (SUCCEEDED(hr)) { - hr = IUnknown_QueryInterface(fimpl->punkFilterMapper2, &IID_IFilterMapper2, (LPVOID*)&fimpl->pFilterMapper2); - } + if (SUCCEEDED(hr)) + hr = IUnknown_QueryInterface(fimpl->punkFilterMapper2, &IID_IFilterMapper2, + (void**)&fimpl->pFilterMapper2); - if (SUCCEEDED(hr)) { + if (SUCCEEDED(hr)) /* Release controlling IUnknown - compensate refcount increase from caching IFilterMapper2 interface. */ - if (pUnkOuter) IUnknown_Release(pUnkOuter); - else IUnknown_Release((IUnknown*)&fimpl->IInner_vtbl); - } + IUnknown_Release(fimpl->outer_unk); if (FAILED(hr)) { ERR("Unable to create filter mapper (%x)\n", hr); @@ -5521,9 +5694,8 @@ HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj) CoTaskMemFree(fimpl); return hr; } - IFilterGraph2_SetDefaultSyncSource((IFilterGraph2*)fimpl); - *ppObj = fimpl; + *ppObj = &fimpl->IUnknown_inner; return S_OK; } diff --git a/reactos/dll/directx/quartz/filtermapper.c b/reactos/dll/directx/quartz/filtermapper.c index 5946da86964..f86c88e654f 100644 --- a/reactos/dll/directx/quartz/filtermapper.c +++ b/reactos/dll/directx/quartz/filtermapper.c @@ -1,5 +1,5 @@ /* - * IFilterMapper & IFilterMapper2 Implementations + * IFilterMapper & IFilterMapper3 Implementations * * Copyright 2003 Robert Shearman * Copyright 2004 Christian Costa @@ -19,8 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#define NONAMELESSUNION -#define NONAMELESSSTRUCT //#include //#include "windef.h" @@ -36,6 +34,8 @@ //#include "strmif.h" #include //#include "uuids.h" +#include +#include #include @@ -43,79 +43,34 @@ WINE_DEFAULT_DEBUG_CHANNEL(quartz); #define ARRAYSIZE(array) (sizeof(array)/sizeof((array)[0])) -/* Unexposed IAMFilterData interface */ -typedef struct IAMFilterData IAMFilterData; - -typedef struct IAMFilterDataVtbl +typedef struct FilterMapper3Impl { - BEGIN_INTERFACE + IUnknown IUnknown_inner; + IFilterMapper3 IFilterMapper3_iface; + IFilterMapper IFilterMapper_iface; + IAMFilterData IAMFilterData_iface; + IUnknown *outer_unk; + LONG ref; +} FilterMapper3Impl; - /*** IUnknown methods ***/ - HRESULT (STDMETHODCALLTYPE *QueryInterface)( - IAMFilterData *This, - REFIID riid, - void **ppvObject); - - ULONG (STDMETHODCALLTYPE *AddRef)( - IAMFilterData *This); - - ULONG (STDMETHODCALLTYPE *Release)( - IAMFilterData *This); - - /*** IAMFilterData methods ***/ - HRESULT (STDMETHODCALLTYPE *ParseFilterData)( - IAMFilterData *This, - BYTE *pData, - ULONG cb, - BYTE **ppRegFilter2); - - HRESULT (STDMETHODCALLTYPE *CreateFilterData)( - IAMFilterData* This, - REGFILTER2 *prf2, - BYTE **pRegFilterData, - ULONG *pcb); - - END_INTERFACE -} IAMFilterDataVtbl; -struct IAMFilterData +static inline FilterMapper3Impl *impl_from_IFilterMapper3( IFilterMapper3 *iface ) { - const IAMFilterDataVtbl *lpVtbl; -}; -static const GUID IID_IAMFilterData = { - 0x97f7c4d4, 0x547b, 0x4a5f, { 0x83,0x32, 0x53,0x64,0x30,0xad,0x2e,0x4d } -}; - - -typedef struct FilterMapper2Impl -{ - const IFilterMapper2Vtbl *lpVtbl; - const IFilterMapperVtbl *lpVtblFilterMapper; - const IAMFilterDataVtbl *lpVtblAMFilterData; - const IUnknownVtbl *IInner_vtbl; - LONG refCount; - IUnknown * pUnkOuter; - BOOL bUnkOuterValid; - BOOL bAggregatable; -} FilterMapper2Impl; - -static const IUnknownVtbl IInner_VTable; -static const IFilterMapper2Vtbl fm2vtbl; -static const IFilterMapperVtbl fmvtbl; -static const IAMFilterDataVtbl AMFilterDataVtbl; - -static inline FilterMapper2Impl *impl_from_IFilterMapper( IFilterMapper *iface ) -{ - return (FilterMapper2Impl *)((char*)iface - FIELD_OFFSET(FilterMapper2Impl, lpVtblFilterMapper)); + return CONTAINING_RECORD(iface, FilterMapper3Impl, IFilterMapper3_iface); } -static inline FilterMapper2Impl *impl_from_IAMFilterData( IAMFilterData *iface ) +static inline FilterMapper3Impl *impl_from_IFilterMapper( IFilterMapper *iface ) { - return (FilterMapper2Impl *)((char*)iface - FIELD_OFFSET(FilterMapper2Impl, lpVtblAMFilterData)); + return CONTAINING_RECORD(iface, FilterMapper3Impl, IFilterMapper_iface); } -static inline FilterMapper2Impl *impl_from_inner_IUnknown( IUnknown *iface ) +static inline FilterMapper3Impl *impl_from_IAMFilterData( IAMFilterData *iface ) { - return (FilterMapper2Impl *)((char*)iface - FIELD_OFFSET(FilterMapper2Impl, IInner_vtbl)); + return CONTAINING_RECORD(iface, FilterMapper3Impl, IAMFilterData_iface); +} + +static inline FilterMapper3Impl *impl_from_IUnknown( IUnknown *iface ) +{ + return CONTAINING_RECORD(iface, FilterMapper3Impl, IUnknown_inner); } static const WCHAR wszClsidSlash[] = {'C','L','S','I','D','\\',0}; @@ -218,68 +173,23 @@ static void delete_vector(struct Vector * v) v->capacity = 0; } -HRESULT FilterMapper2_create(IUnknown *pUnkOuter, LPVOID *ppObj) -{ - FilterMapper2Impl * pFM2impl; - - TRACE("(%p, %p)\n", pUnkOuter, ppObj); - - pFM2impl = CoTaskMemAlloc(sizeof(*pFM2impl)); - if (!pFM2impl) - return E_OUTOFMEMORY; - - pFM2impl->pUnkOuter = pUnkOuter; - pFM2impl->bUnkOuterValid = FALSE; - pFM2impl->bAggregatable = FALSE; - pFM2impl->IInner_vtbl = &IInner_VTable; - pFM2impl->lpVtbl = &fm2vtbl; - pFM2impl->lpVtblFilterMapper = &fmvtbl; - pFM2impl->lpVtblAMFilterData = &AMFilterDataVtbl; - pFM2impl->refCount = 1; - - *ppObj = pFM2impl; - - TRACE("-- created at %p\n", pFM2impl); - - return S_OK; -} - -HRESULT FilterMapper_create(IUnknown *pUnkOuter, LPVOID *ppObj) -{ - FilterMapper2Impl *pFM2impl; - HRESULT hr; - - TRACE("(%p, %p)\n", pUnkOuter, ppObj); - - hr = FilterMapper2_create(pUnkOuter, (LPVOID*)&pFM2impl); - if (FAILED(hr)) - return hr; - - *ppObj = &pFM2impl->lpVtblFilterMapper; - - return hr; -} - /*** IUnknown (inner) methods ***/ -static HRESULT WINAPI Inner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv) +static HRESULT WINAPI Inner_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) { - FilterMapper2Impl *This = impl_from_inner_IUnknown(iface); + FilterMapper3Impl *This = impl_from_IUnknown(iface); + TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv); - if (This->bAggregatable) - This->bUnkOuterValid = TRUE; - *ppv = NULL; - if (IsEqualIID(riid, &IID_IUnknown)) - *ppv = &This->IInner_vtbl; - else if (IsEqualIID(riid, &IID_IFilterMapper2)) - *ppv = This; + *ppv = &This->IUnknown_inner; + else if (IsEqualIID(riid, &IID_IFilterMapper2) || IsEqualIID(riid, &IID_IFilterMapper3)) + *ppv = &This->IFilterMapper3_iface; else if (IsEqualIID(riid, &IID_IFilterMapper)) - *ppv = &This->lpVtblFilterMapper; + *ppv = &This->IFilterMapper_iface; else if (IsEqualIID(riid, &IID_IAMFilterData)) - *ppv = &This->lpVtblAMFilterData; + *ppv = &This->IAMFilterData_iface; if (*ppv != NULL) { @@ -291,29 +201,27 @@ static HRESULT WINAPI Inner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID return E_NOINTERFACE; } -static ULONG WINAPI Inner_AddRef(IUnknown * iface) +static ULONG WINAPI Inner_AddRef(IUnknown *iface) { - FilterMapper2Impl *This = impl_from_inner_IUnknown(iface); - ULONG refCount = InterlockedIncrement(&This->refCount); + FilterMapper3Impl *This = impl_from_IUnknown(iface); + ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p)->() AddRef from %d\n", This, refCount - 1); + TRACE("(%p)->(): new ref = %d\n", This, ref); - return refCount; + return ref; } -static ULONG WINAPI Inner_Release(IUnknown * iface) +static ULONG WINAPI Inner_Release(IUnknown *iface) { - FilterMapper2Impl *This = impl_from_inner_IUnknown(iface); - ULONG refCount = InterlockedDecrement(&This->refCount); + FilterMapper3Impl *This = impl_from_IUnknown(iface); + ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p)->() Release from %d\n", This, refCount + 1); + TRACE("(%p)->(): new ref = %d\n", This, ref); - if (refCount == 0) - { + if (ref == 0) CoTaskMemFree(This); - return 0; - } - return refCount; + + return ref; } static const IUnknownVtbl IInner_VTable = @@ -323,58 +231,31 @@ static const IUnknownVtbl IInner_VTable = Inner_Release }; -static HRESULT WINAPI FilterMapper2_QueryInterface(IFilterMapper2 * iface, REFIID riid, LPVOID *ppv) +static HRESULT WINAPI FilterMapper3_QueryInterface(IFilterMapper3 * iface, REFIID riid, LPVOID *ppv) { - FilterMapper2Impl *This = (FilterMapper2Impl *)iface; + FilterMapper3Impl *This = impl_from_IFilterMapper3(iface); - if (This->bAggregatable) - This->bUnkOuterValid = TRUE; - - if (This->pUnkOuter) - { - if (This->bAggregatable) - return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv); - - if (IsEqualIID(riid, &IID_IUnknown)) - { - HRESULT hr; - - IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl)); - hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv); - IUnknown_Release((IUnknown *)&(This->IInner_vtbl)); - This->bAggregatable = TRUE; - return hr; - } - - *ppv = NULL; - return E_NOINTERFACE; - } - - return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv); + return IUnknown_QueryInterface(This->outer_unk, riid, ppv); } -static ULONG WINAPI FilterMapper2_AddRef(IFilterMapper2 * iface) +static ULONG WINAPI FilterMapper3_AddRef(IFilterMapper3 * iface) { - FilterMapper2Impl *This = (FilterMapper2Impl *)iface; + FilterMapper3Impl *This = impl_from_IFilterMapper3(iface); - if (This->pUnkOuter && This->bUnkOuterValid) - return IUnknown_AddRef(This->pUnkOuter); - return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl)); + return IUnknown_AddRef(This->outer_unk); } -static ULONG WINAPI FilterMapper2_Release(IFilterMapper2 * iface) +static ULONG WINAPI FilterMapper3_Release(IFilterMapper3 * iface) { - FilterMapper2Impl *This = (FilterMapper2Impl *)iface; + FilterMapper3Impl *This = impl_from_IFilterMapper3(iface); - if (This->pUnkOuter && This->bUnkOuterValid) - return IUnknown_Release(This->pUnkOuter); - return IUnknown_Release((IUnknown *)&(This->IInner_vtbl)); + return IUnknown_Release(This->outer_unk); } -/*** IFilterMapper2 methods ***/ +/*** IFilterMapper3 methods ***/ -static HRESULT WINAPI FilterMapper2_CreateCategory( - IFilterMapper2 * iface, +static HRESULT WINAPI FilterMapper3_CreateCategory( + IFilterMapper3 * iface, REFCLSID clsidCategory, DWORD dwCategoryMerit, LPCWSTR szDescription) @@ -431,8 +312,8 @@ static HRESULT WINAPI FilterMapper2_CreateCategory( return hr; } -static HRESULT WINAPI FilterMapper2_UnregisterFilter( - IFilterMapper2 * iface, +static HRESULT WINAPI FilterMapper3_UnregisterFilter( + IFilterMapper3 * iface, const CLSID *pclsidCategory, const OLECHAR *szInstance, REFCLSID Filter) @@ -520,24 +401,24 @@ static HRESULT FM2_WriteFilterData(const REGFILTER2 * prf2, BYTE **ppData, ULONG rrf.dwVersion = prf2->dwVersion; rrf.dwMerit = prf2->dwMerit; - rrf.dwPins = prf2->u.s1.cPins2; + rrf.dwPins = prf2->cPins2; rrf.dwUnused = 0; add_data(&mainStore, (LPBYTE)&rrf, sizeof(rrf)); - for (i = 0; i < prf2->u.s1.cPins2; i++) + for (i = 0; i < prf2->cPins2; i++) { size += sizeof(struct REG_RFP); - if (prf2->u.s1.rgPins2[i].clsPinCategory) + if (prf2->rgPins2[i].clsPinCategory) size += sizeof(DWORD); - size += prf2->u.s1.rgPins2[i].nMediaTypes * sizeof(struct REG_TYPE); - size += prf2->u.s1.rgPins2[i].nMediums * sizeof(DWORD); + size += prf2->rgPins2[i].nMediaTypes * sizeof(struct REG_TYPE); + size += prf2->rgPins2[i].nMediums * sizeof(DWORD); } - for (i = 0; i < prf2->u.s1.cPins2; i++) + for (i = 0; i < prf2->cPins2; i++) { struct REG_RFP rrfp; - REGFILTERPINS2 rgPin2 = prf2->u.s1.rgPins2[i]; + REGFILTERPINS2 rgPin2 = prf2->rgPins2[i]; unsigned int j; rrfp.signature[0] = '0'; @@ -639,9 +520,9 @@ static HRESULT FM2_ReadFilterData(BYTE *pData, REGFILTER2 * prf2) prf2->dwVersion = prrf->dwVersion; prf2->dwMerit = prrf->dwMerit; - prf2->u.s1.cPins2 = prrf->dwPins; + prf2->cPins2 = prrf->dwPins; rgPins2 = CoTaskMemAlloc(prrf->dwPins * sizeof(*rgPins2)); - prf2->u.s1.rgPins2 = rgPins2; + prf2->rgPins2 = rgPins2; pCurrent += sizeof(struct REG_RF); for (i = 0; i < prrf->dwPins; i++) @@ -723,25 +604,25 @@ static HRESULT FM2_ReadFilterData(BYTE *pData, REGFILTER2 * prf2) static void FM2_DeleteRegFilter(REGFILTER2 * prf2) { UINT i; - for (i = 0; i < prf2->u.s1.cPins2; i++) + for (i = 0; i < prf2->cPins2; i++) { UINT j; - if (prf2->u.s1.rgPins2[i].clsPinCategory) - CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2[i].clsPinCategory); + if (prf2->rgPins2[i].clsPinCategory) + CoTaskMemFree((LPVOID)prf2->rgPins2[i].clsPinCategory); - for (j = 0; j < prf2->u.s1.rgPins2[i].nMediaTypes; j++) + for (j = 0; j < prf2->rgPins2[i].nMediaTypes; j++) { - CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2[i].lpMediaType[j].clsMajorType); - CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2[i].lpMediaType[j].clsMinorType); + CoTaskMemFree((LPVOID)prf2->rgPins2[i].lpMediaType[j].clsMajorType); + CoTaskMemFree((LPVOID)prf2->rgPins2[i].lpMediaType[j].clsMinorType); } - CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2[i].lpMediaType); - CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2[i].lpMedium); + CoTaskMemFree((LPVOID)prf2->rgPins2[i].lpMediaType); + CoTaskMemFree((LPVOID)prf2->rgPins2[i].lpMedium); } - CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2); + CoTaskMemFree((LPVOID)prf2->rgPins2); } -static HRESULT WINAPI FilterMapper2_RegisterFilter( - IFilterMapper2 * iface, +static HRESULT WINAPI FilterMapper3_RegisterFilter( + IFilterMapper3 * iface, REFCLSID clsidFilter, LPCWSTR szName, IMoniker **ppMoniker, @@ -782,24 +663,24 @@ static HRESULT WINAPI FilterMapper2_RegisterFilter( /* REGFILTER2 structure is converted from version 1 to 2. Tested on Win2k. */ regfilter2.dwVersion = 2; regfilter2.dwMerit = prf2->dwMerit; - regfilter2.u.s1.cPins2 = prf2->u.s.cPins; - pregfp2 = CoTaskMemAlloc(prf2->u.s.cPins * sizeof(REGFILTERPINS2)); - regfilter2.u.s1.rgPins2 = pregfp2; - for (i = 0; i < prf2->u.s.cPins; i++) + regfilter2.cPins2 = prf2->cPins; + pregfp2 = CoTaskMemAlloc(prf2->cPins * sizeof(REGFILTERPINS2)); + regfilter2.rgPins2 = pregfp2; + for (i = 0; i < prf2->cPins; i++) { flags = 0; - if (prf2->u.s.rgPins[i].bRendered) + if (prf2->rgPins[i].bRendered) flags |= REG_PINFLAG_B_RENDERER; - if (prf2->u.s.rgPins[i].bOutput) + if (prf2->rgPins[i].bOutput) flags |= REG_PINFLAG_B_OUTPUT; - if (prf2->u.s.rgPins[i].bZero) + if (prf2->rgPins[i].bZero) flags |= REG_PINFLAG_B_ZERO; - if (prf2->u.s.rgPins[i].bMany) + if (prf2->rgPins[i].bMany) flags |= REG_PINFLAG_B_MANY; pregfp2[i].dwFlags = flags; pregfp2[i].cInstances = 1; - pregfp2[i].nMediaTypes = prf2->u.s.rgPins[i].nMediaTypes; - pregfp2[i].lpMediaType = prf2->u.s.rgPins[i].lpMediaType; + pregfp2[i].nMediaTypes = prf2->rgPins[i].nMediaTypes; + pregfp2[i].lpMediaType = prf2->rgPins[i].lpMediaType; pregfp2[i].nMediums = 0; pregfp2[i].lpMedium = NULL; pregfp2[i].clsPinCategory = NULL; @@ -992,8 +873,8 @@ static int mm_compare(const void * left, const void * right) * meaning match any input/output pin as long as one exists), otherwise match any * filter that meets the rest of the requirements. */ -static HRESULT WINAPI FilterMapper2_EnumMatchingFilters( - IFilterMapper2 * iface, +static HRESULT WINAPI FilterMapper3_EnumMatchingFilters( + IFilterMapper3 * iface, IEnumMoniker **ppEnum, DWORD dwFlags, BOOL bExactMatch, @@ -1141,9 +1022,9 @@ static HRESULT WINAPI FilterMapper2_EnumMatchingFilters( /* determine whether filter meets requirements */ if (SUCCEEDED(hrSub) && (rf2.dwMerit >= dwMerit)) { - for (i = 0; (i < rf2.u.s1.cPins2) && (!bInputMatch || !bOutputMatch); i++) + for (i = 0; (i < rf2.cPins2) && (!bInputMatch || !bOutputMatch); i++) { - const REGFILTERPINS2 * rfp2 = rf2.u.s1.rgPins2 + i; + const REGFILTERPINS2 * rfp2 = rf2.rgPins2 + i; bInputMatch = bInputMatch || (!(rfp2->dwFlags & REG_PINFLAG_B_OUTPUT) && (!bRender || (rfp2->dwFlags & REG_PINFLAG_B_RENDERER)) && @@ -1204,42 +1085,51 @@ static HRESULT WINAPI FilterMapper2_EnumMatchingFilters( return hr; } -static const IFilterMapper2Vtbl fm2vtbl = +static HRESULT WINAPI FilterMapper3_GetICreateDevEnum(IFilterMapper3 *iface, ICreateDevEnum **ppEnum) +{ + TRACE("(%p, %p)\n", iface, ppEnum); + if (!ppEnum) + return E_POINTER; + return CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, &IID_ICreateDevEnum, (void**)ppEnum); +} + +static const IFilterMapper3Vtbl fm3vtbl = { - FilterMapper2_QueryInterface, - FilterMapper2_AddRef, - FilterMapper2_Release, + FilterMapper3_QueryInterface, + FilterMapper3_AddRef, + FilterMapper3_Release, - FilterMapper2_CreateCategory, - FilterMapper2_UnregisterFilter, - FilterMapper2_RegisterFilter, - FilterMapper2_EnumMatchingFilters + FilterMapper3_CreateCategory, + FilterMapper3_UnregisterFilter, + FilterMapper3_RegisterFilter, + FilterMapper3_EnumMatchingFilters, + FilterMapper3_GetICreateDevEnum }; /*** IUnknown methods ***/ static HRESULT WINAPI FilterMapper_QueryInterface(IFilterMapper * iface, REFIID riid, LPVOID *ppv) { - FilterMapper2Impl *This = impl_from_IFilterMapper(iface); + FilterMapper3Impl *This = impl_from_IFilterMapper(iface); TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv); - return FilterMapper2_QueryInterface((IFilterMapper2*)&This->lpVtbl, riid, ppv); + return FilterMapper3_QueryInterface(&This->IFilterMapper3_iface, riid, ppv); } static ULONG WINAPI FilterMapper_AddRef(IFilterMapper * iface) { - FilterMapper2Impl *This = impl_from_IFilterMapper(iface); + FilterMapper3Impl *This = impl_from_IFilterMapper(iface); - return FilterMapper2_AddRef((IFilterMapper2*)This); + return IUnknown_AddRef(This->outer_unk); } static ULONG WINAPI FilterMapper_Release(IFilterMapper * iface) { - FilterMapper2Impl *This = impl_from_IFilterMapper(iface); + FilterMapper3Impl *This = impl_from_IFilterMapper(iface); - return FilterMapper2_Release((IFilterMapper2*)This); + return IUnknown_Release(This->outer_unk); } /*** IFilterMapper methods ***/ @@ -1256,7 +1146,7 @@ static HRESULT WINAPI FilterMapper_EnumMatchingFilters( CLSID clsOutMaj, CLSID clsOutSub) { - FilterMapper2Impl *This = impl_from_IFilterMapper(iface); + FilterMapper3Impl *This = impl_from_IFilterMapper(iface); GUID InputType[2]; GUID OutputType[2]; IEnumMoniker* ppEnumMoniker; @@ -1285,22 +1175,9 @@ static HRESULT WINAPI FilterMapper_EnumMatchingFilters( *ppEnum = NULL; - hr = IFilterMapper2_EnumMatchingFilters((IFilterMapper2*)This, - &ppEnumMoniker, - 0, - TRUE, - dwMerit, - bInputNeeded, - 1, - InputType, - NULL, - &GUID_NULL, - bRender, - bOutputNeeded, - 1, - OutputType, - NULL, - &GUID_NULL); + hr = IFilterMapper3_EnumMatchingFilters(&This->IFilterMapper3_iface, &ppEnumMoniker, 0, TRUE, + dwMerit, bInputNeeded, 1, InputType, NULL, &GUID_NULL, bRender, bOutputNeeded, 1, + OutputType, NULL, &GUID_NULL); if (FAILED(hr)) return hr; @@ -1745,23 +1622,23 @@ static const IFilterMapperVtbl fmvtbl = /*** IUnknown methods ***/ static HRESULT WINAPI AMFilterData_QueryInterface(IAMFilterData * iface, REFIID riid, LPVOID *ppv) { - FilterMapper2Impl *This = impl_from_IAMFilterData(iface); + FilterMapper3Impl *This = impl_from_IAMFilterData(iface); - return FilterMapper2_QueryInterface((IFilterMapper2*)This, riid, ppv); + return IUnknown_QueryInterface(This->outer_unk, riid, ppv); } static ULONG WINAPI AMFilterData_AddRef(IAMFilterData * iface) { - FilterMapper2Impl *This = impl_from_IAMFilterData(iface); + FilterMapper3Impl *This = impl_from_IAMFilterData(iface); - return FilterMapper2_AddRef((IFilterMapper2*)This); + return IUnknown_AddRef(This->outer_unk); } static ULONG WINAPI AMFilterData_Release(IAMFilterData * iface) { - FilterMapper2Impl *This = impl_from_IAMFilterData(iface); + FilterMapper3Impl *This = impl_from_IAMFilterData(iface); - return FilterMapper2_Release((IFilterMapper2*)This); + return IUnknown_Release(This->outer_unk); } /*** IAMFilterData methods ***/ @@ -1769,16 +1646,16 @@ static HRESULT WINAPI AMFilterData_ParseFilterData(IAMFilterData* iface, BYTE *pData, ULONG cb, BYTE **ppRegFilter2) { - FilterMapper2Impl *This = impl_from_IAMFilterData(iface); + FilterMapper3Impl *This = impl_from_IAMFilterData(iface); HRESULT hr = S_OK; - REGFILTER2 *prf2; + static REGFILTER2 *prf2; TRACE("(%p/%p)->(%p, %d, %p)\n", This, iface, pData, cb, ppRegFilter2); prf2 = CoTaskMemAlloc(sizeof(*prf2)); if (!prf2) return E_OUTOFMEMORY; - *ppRegFilter2 = (BYTE *)prf2; + *ppRegFilter2 = (BYTE *)&prf2; hr = FM2_ReadFilterData(pData, prf2); if (FAILED(hr)) @@ -1795,7 +1672,7 @@ static HRESULT WINAPI AMFilterData_CreateFilterData(IAMFilterData* iface, BYTE **pRegFilterData, ULONG *pcb) { - FilterMapper2Impl *This = impl_from_IAMFilterData(iface); + FilterMapper3Impl *This = impl_from_IAMFilterData(iface); TRACE("(%p/%p)->(%p, %p, %p)\n", This, iface, prf2, pRegFilterData, pcb); @@ -1809,3 +1686,47 @@ static const IAMFilterDataVtbl AMFilterDataVtbl = { AMFilterData_ParseFilterData, AMFilterData_CreateFilterData }; + +HRESULT FilterMapper2_create(IUnknown *pUnkOuter, LPVOID *ppObj) +{ + FilterMapper3Impl * pFM2impl; + + TRACE("(%p, %p)\n", pUnkOuter, ppObj); + + pFM2impl = CoTaskMemAlloc(sizeof(*pFM2impl)); + if (!pFM2impl) + return E_OUTOFMEMORY; + + pFM2impl->IUnknown_inner.lpVtbl = &IInner_VTable; + pFM2impl->IFilterMapper3_iface.lpVtbl = &fm3vtbl; + pFM2impl->IFilterMapper_iface.lpVtbl = &fmvtbl; + pFM2impl->IAMFilterData_iface.lpVtbl = &AMFilterDataVtbl; + pFM2impl->ref = 1; + + if (pUnkOuter) + pFM2impl->outer_unk = pUnkOuter; + else + pFM2impl->outer_unk = &pFM2impl->IUnknown_inner; + + *ppObj = &pFM2impl->IUnknown_inner; + + TRACE("-- created at %p\n", pFM2impl); + + return S_OK; +} + +HRESULT FilterMapper_create(IUnknown *pUnkOuter, LPVOID *ppObj) +{ + FilterMapper3Impl *pFM2impl; + HRESULT hr; + + TRACE("(%p, %p)\n", pUnkOuter, ppObj); + + hr = FilterMapper2_create(pUnkOuter, (LPVOID*)&pFM2impl); + if (FAILED(hr)) + return hr; + + *ppObj = &pFM2impl->IFilterMapper_iface; + + return hr; +} diff --git a/reactos/dll/directx/quartz/main.c b/reactos/dll/directx/quartz/main.c index c3124dd1d53..81844c64296 100644 --- a/reactos/dll/directx/quartz/main.c +++ b/reactos/dll/directx/quartz/main.c @@ -2,9 +2,6 @@ * * Copyright 2002 Lionel Ulmer * - * This file contains the (internal) driver registration functions, - * driver enumeration APIs and DirectDraw creation functions. - * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -40,16 +37,25 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) return QUARTZ_DllMain( hInstDLL, fdwReason, lpv ); } +static HRESULT SeekingPassThru_create(IUnknown *pUnkOuter, LPVOID *ppObj) +{ + return PosPassThru_Construct(pUnkOuter,ppObj); /* from strmbase */ +} + /****************************************************************************** * DirectShow ClassFactory */ typedef struct { - IClassFactory ITF_IClassFactory; - + IClassFactory IClassFactory_iface; LONG ref; HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj); } IClassFactoryImpl; +static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface) +{ + return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface); +} + struct object_creation_info { const CLSID *clsid; @@ -69,6 +75,7 @@ static const struct object_creation_info object_creation[] = { &CLSID_MPEG1Splitter, MPEGSplitter_create }, { &CLSID_VideoRenderer, VideoRenderer_create }, { &CLSID_NullRenderer, NullRenderer_create }, + { &CLSID_VideoMixingRenderer9, VMR9Impl_create }, { &CLSID_VideoRendererDefault, VideoRendererDefault_create }, { &CLSID_DSoundRender, DSoundRender_create }, { &CLSID_AudioRender, DSoundRender_create }, @@ -78,34 +85,30 @@ static const struct object_creation_info object_creation[] = { &CLSID_WAVEParser, WAVEParser_create } }; -static HRESULT WINAPI -DSCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) +static HRESULT WINAPI DSCF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IClassFactory)) { IClassFactory_AddRef(iface); - *ppobj = This; + *ppobj = iface; return S_OK; } *ppobj = NULL; - WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj); + WARN("(%p)->(%s,%p), not found\n", iface, debugstr_guid(riid), ppobj); return E_NOINTERFACE; } -static ULONG WINAPI DSCF_AddRef(LPCLASSFACTORY iface) +static ULONG WINAPI DSCF_AddRef(IClassFactory *iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; + IClassFactoryImpl *This = impl_from_IClassFactory(iface); return InterlockedIncrement(&This->ref); } -static ULONG WINAPI DSCF_Release(LPCLASSFACTORY iface) +static ULONG WINAPI DSCF_Release(IClassFactory *iface) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - + IClassFactoryImpl *This = impl_from_IClassFactory(iface); ULONG ref = InterlockedDecrement(&This->ref); if (ref == 0) @@ -115,16 +118,19 @@ static ULONG WINAPI DSCF_Release(LPCLASSFACTORY iface) } -static HRESULT WINAPI DSCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, - REFIID riid, LPVOID *ppobj) +static HRESULT WINAPI DSCF_CreateInstance(IClassFactory *iface, IUnknown *pOuter, + REFIID riid, void **ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; + IClassFactoryImpl *This = impl_from_IClassFactory(iface); HRESULT hres; LPUNKNOWN punk; - + TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj); *ppobj = NULL; + if(pOuter && !IsEqualGUID(&IID_IUnknown, riid)) + return E_NOINTERFACE; + hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk); if (SUCCEEDED(hres)) { hres = IUnknown_QueryInterface(punk, riid, ppobj); @@ -133,9 +139,9 @@ static HRESULT WINAPI DSCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter return hres; } -static HRESULT WINAPI DSCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) +static HRESULT WINAPI DSCF_LockServer(IClassFactory *iface, BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; + IClassFactoryImpl *This = impl_from_IClassFactory(iface); FIXME("(%p)->(%d),stub!\n",This,dolock); return S_OK; } @@ -181,12 +187,12 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) IClassFactoryImpl *factory = CoTaskMemAlloc(sizeof(*factory)); if (factory == NULL) return E_OUTOFMEMORY; - factory->ITF_IClassFactory.lpVtbl = &DSCF_Vtbl; + factory->IClassFactory_iface.lpVtbl = &DSCF_Vtbl; factory->ref = 1; factory->pfnCreateInstance = object_creation[i].pfnCreateInstance; - *ppv = &factory->ITF_IClassFactory; + *ppv = &factory->IClassFactory_iface; return S_OK; } } @@ -295,17 +301,15 @@ LONG WINAPI DBToAmpFactor(LONG db) */ DWORD WINAPI AMGetErrorTextA(HRESULT hr, LPSTR buffer, DWORD maxlen) { - unsigned int len; - static const char format[] = "Error: 0x%x"; - char error[MAX_ERROR_TEXT_LEN]; + DWORD res; + WCHAR errorW[MAX_ERROR_TEXT_LEN]; - FIXME("(%x,%p,%d) stub\n", hr, buffer, maxlen); + TRACE("(%x,%p,%d)\n", hr, buffer, maxlen); + if (!buffer) + return 0; - if (!buffer) return 0; - wsprintfA(error, format, hr); - if ((len = strlen(error)) >= maxlen) return 0; - lstrcpyA(buffer, error); - return len; + res = AMGetErrorTextW(hr, errorW, sizeof(errorW)/sizeof(*errorW)); + return WideCharToMultiByte(CP_ACP, 0, errorW, res, buffer, maxlen, 0, 0); } /*********************************************************************** diff --git a/reactos/dll/directx/quartz/memallocator.c b/reactos/dll/directx/quartz/memallocator.c index 01a13b359a1..96fdb35ed24 100644 --- a/reactos/dll/directx/quartz/memallocator.c +++ b/reactos/dll/directx/quartz/memallocator.c @@ -31,9 +31,20 @@ WINE_DEFAULT_DEBUG_CHANNEL(quartz); +typedef struct StdMediaSample2 +{ + IMediaSample2 IMediaSample2_iface; + LONG ref; + AM_SAMPLE2_PROPERTIES props; + IMemAllocator * pParent; + struct list listentry; + LONGLONG tMediaStart; + LONGLONG tMediaEnd; +} StdMediaSample2; + typedef struct BaseMemAllocator { - const IMemAllocatorVtbl * lpVtbl; + IMemAllocator IMemAllocator_iface; LONG ref; ALLOCATOR_PROPERTIES props; @@ -52,8 +63,14 @@ typedef struct BaseMemAllocator CRITICAL_SECTION *pCritSect; } BaseMemAllocator; +static inline BaseMemAllocator *impl_from_IMemAllocator(IMemAllocator *iface) +{ + return CONTAINING_RECORD(iface, BaseMemAllocator, IMemAllocator_iface); +} + static const IMemAllocatorVtbl BaseMemAllocator_VTable; static const IMediaSample2Vtbl StdMediaSample2_VTable; +static inline StdMediaSample2 *unsafe_impl_from_IMediaSample(IMediaSample * iface); #define AM_SAMPLE2_PROP_SIZE_WRITABLE FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, pbBuffer) @@ -70,7 +87,7 @@ static HRESULT BaseMemAllocator_Init(HRESULT (* fnAlloc)(IMemAllocator *), { assert(fnAlloc && fnFree && fnDestroyed); - pMemAlloc->lpVtbl = &BaseMemAllocator_VTable; + pMemAlloc->IMemAllocator_iface.lpVtbl = &BaseMemAllocator_VTable; pMemAlloc->ref = 1; ZeroMemory(&pMemAlloc->props, sizeof(pMemAlloc->props)); @@ -93,7 +110,7 @@ static HRESULT BaseMemAllocator_Init(HRESULT (* fnAlloc)(IMemAllocator *), static HRESULT WINAPI BaseMemAllocator_QueryInterface(IMemAllocator * iface, REFIID riid, LPVOID * ppv) { - BaseMemAllocator *This = (BaseMemAllocator *)iface; + BaseMemAllocator *This = impl_from_IMemAllocator(iface); TRACE("(%p)->(%s, %p)\n", This, qzdebugstr_guid(riid), ppv); *ppv = NULL; @@ -116,7 +133,7 @@ static HRESULT WINAPI BaseMemAllocator_QueryInterface(IMemAllocator * iface, REF static ULONG WINAPI BaseMemAllocator_AddRef(IMemAllocator * iface) { - BaseMemAllocator *This = (BaseMemAllocator *)iface; + BaseMemAllocator *This = impl_from_IMemAllocator(iface); ULONG ref = InterlockedIncrement(&This->ref); TRACE("(%p)->() AddRef from %d\n", iface, ref - 1); @@ -126,7 +143,7 @@ static ULONG WINAPI BaseMemAllocator_AddRef(IMemAllocator * iface) static ULONG WINAPI BaseMemAllocator_Release(IMemAllocator * iface) { - BaseMemAllocator *This = (BaseMemAllocator *)iface; + BaseMemAllocator *This = impl_from_IMemAllocator(iface); ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p)->() Release from %d\n", iface, ref + 1); @@ -145,7 +162,7 @@ static ULONG WINAPI BaseMemAllocator_Release(IMemAllocator * iface) static HRESULT WINAPI BaseMemAllocator_SetProperties(IMemAllocator * iface, ALLOCATOR_PROPERTIES *pRequest, ALLOCATOR_PROPERTIES *pActual) { - BaseMemAllocator *This = (BaseMemAllocator *)iface; + BaseMemAllocator *This = impl_from_IMemAllocator(iface); HRESULT hr; TRACE("(%p)->(%p, %p)\n", This, pRequest, pActual); @@ -178,7 +195,7 @@ static HRESULT WINAPI BaseMemAllocator_SetProperties(IMemAllocator * iface, ALLO static HRESULT WINAPI BaseMemAllocator_GetProperties(IMemAllocator * iface, ALLOCATOR_PROPERTIES *pProps) { - BaseMemAllocator *This = (BaseMemAllocator *)iface; + BaseMemAllocator *This = impl_from_IMemAllocator(iface); HRESULT hr = S_OK; TRACE("(%p)->(%p)\n", This, pProps); @@ -194,7 +211,7 @@ static HRESULT WINAPI BaseMemAllocator_GetProperties(IMemAllocator * iface, ALLO static HRESULT WINAPI BaseMemAllocator_Commit(IMemAllocator * iface) { - BaseMemAllocator *This = (BaseMemAllocator *)iface; + BaseMemAllocator *This = impl_from_IMemAllocator(iface); HRESULT hr; TRACE("(%p)->()\n", This); @@ -238,7 +255,7 @@ static HRESULT WINAPI BaseMemAllocator_Commit(IMemAllocator * iface) static HRESULT WINAPI BaseMemAllocator_Decommit(IMemAllocator * iface) { - BaseMemAllocator *This = (BaseMemAllocator *)iface; + BaseMemAllocator *This = impl_from_IMemAllocator(iface); HRESULT hr; TRACE("(%p)->()\n", This); @@ -279,7 +296,7 @@ static HRESULT WINAPI BaseMemAllocator_Decommit(IMemAllocator * iface) static HRESULT WINAPI BaseMemAllocator_GetBuffer(IMemAllocator * iface, IMediaSample ** pSample, REFERENCE_TIME *pStartTime, REFERENCE_TIME *pEndTime, DWORD dwFlags) { - BaseMemAllocator *This = (BaseMemAllocator *)iface; + BaseMemAllocator *This = impl_from_IMemAllocator(iface); HRESULT hr = S_OK; /* NOTE: The pStartTime and pEndTime parameters are not applied to the sample. @@ -319,14 +336,14 @@ static HRESULT WINAPI BaseMemAllocator_GetBuffer(IMemAllocator * iface, IMediaSa hr = VFW_E_TIMEOUT; else { + StdMediaSample2 *ms; struct list * free = list_head(&This->free_list); list_remove(free); list_add_head(&This->used_list, free); - *pSample = (IMediaSample *)LIST_ENTRY(free, StdMediaSample2, listentry); - - assert(((StdMediaSample2 *)*pSample)->ref == 0); - + ms = LIST_ENTRY(free, StdMediaSample2, listentry); + assert(ms->ref == 0); + *pSample = (IMediaSample *)&ms->IMediaSample2_iface; IMediaSample_AddRef(*pSample); } } @@ -339,10 +356,10 @@ static HRESULT WINAPI BaseMemAllocator_GetBuffer(IMemAllocator * iface, IMediaSa static HRESULT WINAPI BaseMemAllocator_ReleaseBuffer(IMemAllocator * iface, IMediaSample * pSample) { - BaseMemAllocator *This = (BaseMemAllocator *)iface; - StdMediaSample2 * pStdSample = (StdMediaSample2 *)pSample; + BaseMemAllocator *This = impl_from_IMemAllocator(iface); + StdMediaSample2 * pStdSample = unsafe_impl_from_IMediaSample(pSample); HRESULT hr = S_OK; - + TRACE("(%p)->(%p)\n", This, pSample); /* FIXME: make sure that sample is currently on the used list */ @@ -408,7 +425,7 @@ static HRESULT StdMediaSample2_Construct(BYTE * pbBuffer, LONG cbBuffer, IMemAll if (!(*ppSample = CoTaskMemAlloc(sizeof(StdMediaSample2)))) return E_OUTOFMEMORY; - (*ppSample)->lpvtbl = &StdMediaSample2_VTable; + (*ppSample)->IMediaSample2_iface.lpVtbl = &StdMediaSample2_VTable; (*ppSample)->ref = 0; ZeroMemory(&(*ppSample)->props, sizeof((*ppSample)->props)); @@ -431,47 +448,45 @@ static void StdMediaSample2_Delete(StdMediaSample2 * This) CoTaskMemFree(This); } -static HRESULT WINAPI StdMediaSample2_QueryInterface(IMediaSample2 * iface, REFIID riid, LPVOID * ppv) +static inline StdMediaSample2 *impl_from_IMediaSample2(IMediaSample2 * iface) +{ + return CONTAINING_RECORD(iface, StdMediaSample2, IMediaSample2_iface); +} + +static HRESULT WINAPI StdMediaSample2_QueryInterface(IMediaSample2 * iface, REFIID riid, void ** ppv) { - StdMediaSample2 *This = (StdMediaSample2 *)iface; TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv); *ppv = NULL; - if (IsEqualIID(riid, &IID_IUnknown)) - *ppv = This; - else if (IsEqualIID(riid, &IID_IMediaSample)) - *ppv = This; - else if (IsEqualIID(riid, &IID_IMediaSample2)) - *ppv = This; - - if (*ppv) + if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IMediaSample) || + IsEqualIID(riid, &IID_IMediaSample2)) { - IUnknown_AddRef((IUnknown *)(*ppv)); + *ppv = iface; + IMediaSample2_AddRef(iface); return S_OK; } FIXME("No interface for %s!\n", qzdebugstr_guid(riid)); - return E_NOINTERFACE; } static ULONG WINAPI StdMediaSample2_AddRef(IMediaSample2 * iface) { - StdMediaSample2 *This = (StdMediaSample2 *)iface; + StdMediaSample2 *This = impl_from_IMediaSample2(iface); ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p)->() AddRef from %d\n", iface, ref - 1); + TRACE("(%p)->(): new ref = %d\n", This, ref); return ref; } static ULONG WINAPI StdMediaSample2_Release(IMediaSample2 * iface) { - StdMediaSample2 *This = (StdMediaSample2 *)iface; + StdMediaSample2 *This = impl_from_IMediaSample2(iface); ULONG ref = InterlockedDecrement(&This->ref); - TRACE("(%p)->() Release from %d\n", iface, ref + 1); + TRACE("(%p)->(): new ref = %d\n", This, ref); if (!ref) { @@ -479,14 +494,13 @@ static ULONG WINAPI StdMediaSample2_Release(IMediaSample2 * iface) IMemAllocator_ReleaseBuffer(This->pParent, (IMediaSample *)iface); else StdMediaSample2_Delete(This); - return 0; } return ref; } static HRESULT WINAPI StdMediaSample2_GetPointer(IMediaSample2 * iface, BYTE ** ppBuffer) { - StdMediaSample2 *This = (StdMediaSample2 *)iface; + StdMediaSample2 *This = impl_from_IMediaSample2(iface); TRACE("(%p)->(%p)\n", iface, ppBuffer); @@ -503,7 +517,7 @@ static HRESULT WINAPI StdMediaSample2_GetPointer(IMediaSample2 * iface, BYTE ** static LONG WINAPI StdMediaSample2_GetSize(IMediaSample2 * iface) { - StdMediaSample2 *This = (StdMediaSample2 *)iface; + StdMediaSample2 *This = impl_from_IMediaSample2(iface); TRACE("StdMediaSample2_GetSize()\n"); @@ -512,8 +526,8 @@ static LONG WINAPI StdMediaSample2_GetSize(IMediaSample2 * iface) static HRESULT WINAPI StdMediaSample2_GetTime(IMediaSample2 * iface, REFERENCE_TIME * pStart, REFERENCE_TIME * pEnd) { + StdMediaSample2 *This = impl_from_IMediaSample2(iface); HRESULT hr; - StdMediaSample2 *This = (StdMediaSample2 *)iface; TRACE("(%p)->(%p, %p)\n", iface, pStart, pEnd); @@ -539,7 +553,7 @@ static HRESULT WINAPI StdMediaSample2_GetTime(IMediaSample2 * iface, REFERENCE_T static HRESULT WINAPI StdMediaSample2_SetTime(IMediaSample2 * iface, REFERENCE_TIME * pStart, REFERENCE_TIME * pEnd) { - StdMediaSample2 *This = (StdMediaSample2 *)iface; + StdMediaSample2 *This = impl_from_IMediaSample2(iface); TRACE("(%p)->(%p, %p)\n", iface, pStart, pEnd); @@ -564,7 +578,7 @@ static HRESULT WINAPI StdMediaSample2_SetTime(IMediaSample2 * iface, REFERENCE_T static HRESULT WINAPI StdMediaSample2_IsSyncPoint(IMediaSample2 * iface) { - StdMediaSample2 *This = (StdMediaSample2 *)iface; + StdMediaSample2 *This = impl_from_IMediaSample2(iface); TRACE("(%p)->()\n", iface); @@ -573,7 +587,7 @@ static HRESULT WINAPI StdMediaSample2_IsSyncPoint(IMediaSample2 * iface) static HRESULT WINAPI StdMediaSample2_SetSyncPoint(IMediaSample2 * iface, BOOL bIsSyncPoint) { - StdMediaSample2 *This = (StdMediaSample2 *)iface; + StdMediaSample2 *This = impl_from_IMediaSample2(iface); TRACE("(%p)->(%s)\n", iface, bIsSyncPoint ? "TRUE" : "FALSE"); @@ -587,7 +601,7 @@ static HRESULT WINAPI StdMediaSample2_SetSyncPoint(IMediaSample2 * iface, BOOL b static HRESULT WINAPI StdMediaSample2_IsPreroll(IMediaSample2 * iface) { - StdMediaSample2 *This = (StdMediaSample2 *)iface; + StdMediaSample2 *This = impl_from_IMediaSample2(iface); TRACE("(%p)->()\n", iface); @@ -596,7 +610,7 @@ static HRESULT WINAPI StdMediaSample2_IsPreroll(IMediaSample2 * iface) static HRESULT WINAPI StdMediaSample2_SetPreroll(IMediaSample2 * iface, BOOL bIsPreroll) { - StdMediaSample2 *This = (StdMediaSample2 *)iface; + StdMediaSample2 *This = impl_from_IMediaSample2(iface); TRACE("(%p)->(%s)\n", iface, bIsPreroll ? "TRUE" : "FALSE"); @@ -610,7 +624,7 @@ static HRESULT WINAPI StdMediaSample2_SetPreroll(IMediaSample2 * iface, BOOL bIs static LONG WINAPI StdMediaSample2_GetActualDataLength(IMediaSample2 * iface) { - StdMediaSample2 *This = (StdMediaSample2 *)iface; + StdMediaSample2 *This = impl_from_IMediaSample2(iface); TRACE("(%p)->()\n", iface); @@ -619,7 +633,7 @@ static LONG WINAPI StdMediaSample2_GetActualDataLength(IMediaSample2 * iface) static HRESULT WINAPI StdMediaSample2_SetActualDataLength(IMediaSample2 * iface, LONG len) { - StdMediaSample2 *This = (StdMediaSample2 *)iface; + StdMediaSample2 *This = impl_from_IMediaSample2(iface); TRACE("(%p)->(%d)\n", iface, len); @@ -637,7 +651,7 @@ static HRESULT WINAPI StdMediaSample2_SetActualDataLength(IMediaSample2 * iface, static HRESULT WINAPI StdMediaSample2_GetMediaType(IMediaSample2 * iface, AM_MEDIA_TYPE ** ppMediaType) { - StdMediaSample2 *This = (StdMediaSample2 *)iface; + StdMediaSample2 *This = impl_from_IMediaSample2(iface); TRACE("(%p)->(%p)\n", iface, ppMediaType); @@ -656,13 +670,18 @@ static HRESULT WINAPI StdMediaSample2_GetMediaType(IMediaSample2 * iface, AM_MED static HRESULT WINAPI StdMediaSample2_SetMediaType(IMediaSample2 * iface, AM_MEDIA_TYPE * pMediaType) { - StdMediaSample2 *This = (StdMediaSample2 *)iface; + StdMediaSample2 *This = impl_from_IMediaSample2(iface); TRACE("(%p)->(%p)\n", iface, pMediaType); if (This->props.pMediaType) + { FreeMediaType(This->props.pMediaType); - else if (!(This->props.pMediaType = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE)))) + This->props.pMediaType = NULL; + } + if (!pMediaType) + return S_FALSE; + if (!(This->props.pMediaType = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE)))) return E_OUTOFMEMORY; return CopyMediaType(This->props.pMediaType, pMediaType); @@ -670,7 +689,7 @@ static HRESULT WINAPI StdMediaSample2_SetMediaType(IMediaSample2 * iface, AM_MED static HRESULT WINAPI StdMediaSample2_IsDiscontinuity(IMediaSample2 * iface) { - StdMediaSample2 *This = (StdMediaSample2 *)iface; + StdMediaSample2 *This = impl_from_IMediaSample2(iface); TRACE("(%p)->()\n", iface); @@ -679,7 +698,7 @@ static HRESULT WINAPI StdMediaSample2_IsDiscontinuity(IMediaSample2 * iface) static HRESULT WINAPI StdMediaSample2_SetDiscontinuity(IMediaSample2 * iface, BOOL bIsDiscontinuity) { - StdMediaSample2 *This = (StdMediaSample2 *)iface; + StdMediaSample2 *This = impl_from_IMediaSample2(iface); TRACE("(%p)->(%s)\n", iface, bIsDiscontinuity ? "TRUE" : "FALSE"); @@ -693,7 +712,7 @@ static HRESULT WINAPI StdMediaSample2_SetDiscontinuity(IMediaSample2 * iface, BO static HRESULT WINAPI StdMediaSample2_GetMediaTime(IMediaSample2 * iface, LONGLONG * pStart, LONGLONG * pEnd) { - StdMediaSample2 *This = (StdMediaSample2 *)iface; + StdMediaSample2 *This = impl_from_IMediaSample2(iface); TRACE("(%p)->(%p, %p)\n", iface, pStart, pEnd); @@ -703,12 +722,12 @@ static HRESULT WINAPI StdMediaSample2_GetMediaTime(IMediaSample2 * iface, LONGLO *pStart = This->tMediaStart; *pEnd = This->tMediaEnd; - return E_NOTIMPL; + return S_OK; } static HRESULT WINAPI StdMediaSample2_SetMediaTime(IMediaSample2 * iface, LONGLONG * pStart, LONGLONG * pEnd) { - StdMediaSample2 *This = (StdMediaSample2 *)iface; + StdMediaSample2 *This = impl_from_IMediaSample2(iface); TRACE("(%p)->(%p, %p)\n", iface, pStart, pEnd); @@ -727,7 +746,7 @@ static HRESULT WINAPI StdMediaSample2_SetMediaTime(IMediaSample2 * iface, LONGLO static HRESULT WINAPI StdMediaSample2_GetProperties(IMediaSample2 * iface, DWORD cbProperties, BYTE * pbProperties) { - StdMediaSample2 *This = (StdMediaSample2 *)iface; + StdMediaSample2 *This = impl_from_IMediaSample2(iface); TRACE("(%p)->(%d, %p)\n", iface, cbProperties, pbProperties); @@ -738,7 +757,7 @@ static HRESULT WINAPI StdMediaSample2_GetProperties(IMediaSample2 * iface, DWORD static HRESULT WINAPI StdMediaSample2_SetProperties(IMediaSample2 * iface, DWORD cbProperties, const BYTE * pbProperties) { - StdMediaSample2 *This = (StdMediaSample2 *)iface; + StdMediaSample2 *This = impl_from_IMediaSample2(iface); TRACE("(%p)->(%d, %p)\n", iface, cbProperties, pbProperties); @@ -773,6 +792,16 @@ static const IMediaSample2Vtbl StdMediaSample2_VTable = StdMediaSample2_SetProperties }; +static inline StdMediaSample2 *unsafe_impl_from_IMediaSample(IMediaSample * iface) +{ + IMediaSample2 *iface2 = (IMediaSample2 *)iface; + + if (!iface) + return NULL; + assert(iface2->lpVtbl == &StdMediaSample2_VTable); + return impl_from_IMediaSample2(iface2); +} + typedef struct StdMemAllocator { BaseMemAllocator base; @@ -780,9 +809,14 @@ typedef struct StdMemAllocator LPVOID pMemory; } StdMemAllocator; +static inline StdMemAllocator *StdMemAllocator_from_IMemAllocator(IMemAllocator * iface) +{ + return CONTAINING_RECORD(iface, StdMemAllocator, base.IMemAllocator_iface); +} + static HRESULT StdMemAllocator_Alloc(IMemAllocator * iface) { - StdMemAllocator *This = (StdMemAllocator *)iface; + StdMemAllocator *This = StdMemAllocator_from_IMemAllocator(iface); StdMediaSample2 * pSample = NULL; SYSTEM_INFO si; LONG i; @@ -802,6 +836,9 @@ static HRESULT StdMemAllocator_Alloc(IMemAllocator * iface) /* allocate memory */ This->pMemory = VirtualAlloc(NULL, (This->base.props.cbBuffer + This->base.props.cbPrefix) * This->base.props.cBuffers, MEM_COMMIT, PAGE_READWRITE); + if (!This->pMemory) + return E_OUTOFMEMORY; + for (i = This->base.props.cBuffers - 1; i >= 0; i--) { /* pbBuffer does not start at the base address, it starts at base + cbPrefix */ @@ -817,7 +854,7 @@ static HRESULT StdMemAllocator_Alloc(IMemAllocator * iface) static HRESULT StdMemAllocator_Free(IMemAllocator * iface) { - StdMemAllocator *This = (StdMemAllocator *)iface; + StdMemAllocator *This = StdMemAllocator_from_IMemAllocator(iface); struct list * cursor; if (!list_empty(&This->base.used_list)) @@ -850,7 +887,7 @@ static HRESULT StdMemAllocator_Free(IMemAllocator * iface) static void StdMemAllocator_Destroy(IMemAllocator *iface) { - StdMemAllocator *This = (StdMemAllocator *)iface; + StdMemAllocator *This = StdMemAllocator_from_IMemAllocator(iface); This->csState.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&This->csState); diff --git a/reactos/dll/directx/quartz/mpegsplit.c b/reactos/dll/directx/quartz/mpegsplit.c index 1f002b93f12..9de3f00a343 100644 --- a/reactos/dll/directx/quartz/mpegsplit.c +++ b/reactos/dll/directx/quartz/mpegsplit.c @@ -25,7 +25,6 @@ //#include #include "quartz_private.h" -#include "control_private.h" #include "pin.h" //#include "uuids.h" @@ -53,30 +52,23 @@ WINE_DEFAULT_DEBUG_CHANNEL(quartz); #define MPEG_AUDIO_HEADER 1 #define MPEG_NO_HEADER 0 -#define SEEK_INTERVAL (ULONGLONG)(10 * 10000000) /* Add an entry every 10 seconds */ - -struct seek_entry { - ULONGLONG bytepos; - ULONGLONG timepos; -}; - typedef struct MPEGSplitterImpl { ParserImpl Parser; LONGLONG EndOfFile; - LONGLONG duration; LONGLONG position; DWORD begin_offset; BYTE header[4]; /* Whether we just seeked (or started playing) */ BOOL seek; - - /* Seeking cache */ - ULONG seek_entries; - struct seek_entry *seektable; } MPEGSplitterImpl; +static inline MPEGSplitterImpl *impl_from_IMediaSeeking( IMediaSeeking *iface ) +{ + return CONTAINING_RECORD(iface, MPEGSplitterImpl, Parser.sourceSeeking.IMediaSeeking_iface); +} + static int MPEGSplitter_head_check(const BYTE *header) { /* If this is a possible start code, check for a system or video header */ @@ -120,15 +112,14 @@ static const DWORD tabsel_123[2][3][16] = { static HRESULT parse_header(BYTE *header, LONGLONG *plen, LONGLONG *pduration) { + int bitrate_index, freq_index, lsf = 1, mpeg1, layer, padding, bitrate, length; LONGLONG duration; - int bitrate_index, freq_index, lsf = 1, mpeg1, layer, padding, bitrate, length; - if (!(header[0] == 0xff && ((header[1]>>5)&0x7) == 0x7 && - ((header[1]>>1)&0x3) != 0 && ((header[2]>>4)&0xf) != 0xf && - ((header[2]>>2)&0x3) != 0x3)) + ((header[1]>>1)&0x3) != 0 && ((header[2]>>4)&0xf) != 0xf && + ((header[2]>>2)&0x3) != 0x3)) { - FIXME("Not a valid header: %02x:%02x\n", header[0], header[1]); + FIXME("Not a valid header: %02x:%02x:%02x:%02x\n", header[0], header[1], header[2], header[3]); return E_INVALIDARG; } @@ -142,17 +133,23 @@ static HRESULT parse_header(BYTE *header, LONGLONG *plen, LONGLONG *pduration) padding = ((header[2]>>1)&0x1); bitrate = tabsel_123[lsf][layer-1][bitrate_index] * 1000; - if (!bitrate || layer != 3) + if (!bitrate) { FIXME("Not a valid header: %02x:%02x:%02x:%02x\n", header[0], header[1], header[2], header[3]); return E_INVALIDARG; } - - if (layer == 3 || layer == 2) - length = 144 * bitrate / freqs[freq_index] + padding; - else + if (layer == 1) length = 4 * (12 * bitrate / freqs[freq_index] + padding); + else if (layer == 2) + length = 144 * bitrate / freqs[freq_index] + padding; + else if (layer == 3) + length = 144 * bitrate / (freqs[freq_index]<Parser.ppPins[1]; + Parser_OutputPin * pOutputPin = unsafe_impl_Parser_OutputPin_from_IPin(This->Parser.ppPins[1]); LONGLONG length = 0; LONGLONG pos = BYTES_FROM_MEDIATIME(This->Parser.pInputPin->rtNext); - LONGLONG time = This->position; + LONGLONG time = This->position, rtstop, rtstart; HRESULT hr; BYTE *fbuf = NULL; DWORD len = IMediaSample_GetActualDataLength(pCurrentSample); @@ -175,7 +172,8 @@ static HRESULT FillBuffer(MPEGSplitterImpl *This, IMediaSample *pCurrentSample) IMediaSample_GetPointer(pCurrentSample, &fbuf); /* Find the next valid header.. it be right here */ - assert(parse_header(fbuf, &length, &This->position) == S_OK); + hr = parse_header(fbuf, &length, &This->position); + assert(hr == S_OK); IMediaSample_SetActualDataLength(pCurrentSample, length); /* Queue the next sample */ @@ -212,9 +210,14 @@ static HRESULT FillBuffer(MPEGSplitterImpl *This, IMediaSample *pCurrentSample) IMediaSample_SetPreroll(sample, 0); IMediaSample_SetDiscontinuity(sample, 0); IMediaSample_SetSyncPoint(sample, 1); - pin->rtCurrent = rtSampleStart; - pin->rtNext = rtSampleStop; hr = IAsyncReader_Request(pin->pReader, sample, 0); + if (SUCCEEDED(hr)) + { + pin->rtCurrent = rtSampleStart; + pin->rtNext = rtSampleStop; + } + else + IMediaSample_Release(sample); } if (FAILED(hr)) FIXME("o_Ox%08x\n", hr); @@ -224,9 +227,30 @@ static HRESULT FillBuffer(MPEGSplitterImpl *This, IMediaSample *pCurrentSample) TRACE("Media time : %u.%03u\n", (DWORD)(This->position/10000000), (DWORD)((This->position/10000)%1000)); - IMediaSample_SetTime(pCurrentSample, &time, &This->position); + if (IMediaSample_IsDiscontinuity(pCurrentSample) == S_OK) { + IPin *victim; + EnterCriticalSection(&This->Parser.filter.csFilter); + pOutputPin->pin.pin.tStart = time; + pOutputPin->pin.pin.dRate = This->Parser.sourceSeeking.dRate; + hr = IPin_ConnectedTo(&pOutputPin->pin.pin.IPin_iface, &victim); + if (hr == S_OK) + { + hr = IPin_NewSegment(victim, time, This->Parser.sourceSeeking.llStop, + This->Parser.sourceSeeking.dRate); + if (hr != S_OK) + FIXME("NewSegment returns %08x\n", hr); + IPin_Release(victim); + } + LeaveCriticalSection(&This->Parser.filter.csFilter); + if (hr != S_OK) + return hr; + } + rtstart = (double)(time - pOutputPin->pin.pin.tStart) / pOutputPin->pin.pin.dRate; + rtstop = (double)(This->position - pOutputPin->pin.pin.tStart) / pOutputPin->pin.pin.dRate; + IMediaSample_SetTime(pCurrentSample, &rtstart, &rtstop); + IMediaSample_SetMediaTime(pCurrentSample, &time, &This->position); - hr = OutputPin_SendSample(&pOutputPin->pin, pCurrentSample); + hr = BaseOutputPinImpl_Deliver(&pOutputPin->pin, pCurrentSample); if (hr != S_OK) { @@ -280,7 +304,7 @@ static HRESULT MPEGSplitter_process_sample(LPVOID iface, IMediaSample * pSample, } } - if (BYTES_FROM_MEDIATIME(tStop) >= This->EndOfFile || This->position >= This->Parser.mediaSeeking.llStop) + if (BYTES_FROM_MEDIATIME(tStop) >= This->EndOfFile || This->position >= This->Parser.sourceSeeking.llStop) { unsigned int i; @@ -322,6 +346,7 @@ static HRESULT MPEGSplitter_query_accept(LPVOID iface, const AM_MEDIA_TYPE *pmt) FIXME("MPEG-1 system streams not yet supported.\n"); else if (IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_MPEG1VideoCD)) FIXME("MPEG-1 VideoCD streams not yet supported.\n"); + else FIXME("%s\n", debugstr_guid(&pmt->subtype)); return S_FALSE; } @@ -449,7 +474,7 @@ static HRESULT MPEGSplitter_init_audio(MPEGSplitterImpl *This, const BYTE *heade static HRESULT MPEGSplitter_pre_connect(IPin *iface, IPin *pConnectPin, ALLOCATOR_PROPERTIES *props) { - PullPin *pPin = (PullPin *)iface; + PullPin *pPin = impl_PullPin_from_IPin(iface); MPEGSplitterImpl *This = (MPEGSplitterImpl*)pPin->pin.pinInfo.pFilter; HRESULT hr; LONGLONG pos = 0; /* in bytes */ @@ -469,17 +494,23 @@ static HRESULT MPEGSplitter_pre_connect(IPin *iface, IPin *pConnectPin, ALLOCATO /* Skip ID3 v2 tag, if any */ if (SUCCEEDED(hr) && !memcmp("ID3", header, 3)) do { - UINT length; + UINT length = 0; hr = IAsyncReader_SyncRead(pPin->pReader, pos, 6, header + 4); if (FAILED(hr)) break; pos += 6; TRACE("Found ID3 v2.%d.%d\n", header[3], header[4]); - length = (header[6] & 0x7F) << 21; - length += (header[7] & 0x7F) << 14; - length += (header[8] & 0x7F) << 7; - length += (header[9] & 0x7F); - TRACE("Length: %u\n", length); + if(header[3] <= 4 && header[4] != 0xff && + (header[5]&0x0f) == 0 && (header[6]&0x80) == 0 && + (header[7]&0x80) == 0 && (header[8]&0x80) == 0 && + (header[9]&0x80) == 0) + { + length = (header[6]<<21) | (header[7]<<14) | + (header[8]<< 7) | (header[9] ); + if((header[5]&0x10)) + length += 10; + TRACE("Length: %u\n", length); + } pos += length; /* Read the real header for the mpeg splitter */ @@ -502,22 +533,17 @@ static HRESULT MPEGSplitter_pre_connect(IPin *iface, IPin *pConnectPin, ALLOCATO This->begin_offset = pos; memcpy(This->header, header, 4); - This->seektable[0].bytepos = pos; - This->seektable[0].timepos = 0; - switch(streamtype) { case MPEG_AUDIO_HEADER: { LONGLONG duration = 0; - DWORD last_entry = 0; - - DWORD ticks = GetTickCount(); + WAVEFORMATEX *format; hr = MPEGSplitter_init_audio(This, header, &piOutput, &amt); if (SUCCEEDED(hr)) { - WAVEFORMATEX *format = (WAVEFORMATEX*)amt.pbFormat; + format = (WAVEFORMATEX*)amt.pbFormat; props->cbAlign = 1; props->cbPrefix = 0; @@ -537,59 +563,20 @@ static HRESULT MPEGSplitter_pre_connect(IPin *iface, IPin *pConnectPin, ALLOCATO } /* Check for idv1 tag, and remove it from stream if found */ - hr = IAsyncReader_SyncRead(pPin->pReader, This->EndOfFile-128, 3, header+4); + hr = IAsyncReader_SyncRead(pPin->pReader, This->EndOfFile-128, 3, header); if (FAILED(hr)) break; - if (!strncmp((char*)header+4, "TAG", 3)) + if (!strncmp((char*)header, "TAG", 3)) This->EndOfFile -= 128; This->Parser.pInputPin->rtStop = MEDIATIME_FROM_BYTES(This->EndOfFile); This->Parser.pInputPin->rtStart = This->Parser.pInputPin->rtCurrent = MEDIATIME_FROM_BYTES(This->begin_offset); - /* http://mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm has a whole read up on audio headers */ - while (pos + 3 < This->EndOfFile) - { - LONGLONG length = 0; - hr = IAsyncReader_SyncRead(pPin->pReader, pos, 4, header); - if (hr != S_OK) - break; - while (parse_header(header, &length, &duration)) - { - /* No valid header yet; shift by a byte and check again */ - memmove(header, header+1, 3); - hr = IAsyncReader_SyncRead(pPin->pReader, pos++, 1, header + 3); - if (hr != S_OK || This->EndOfFile - pos < 4) - break; - } - pos += length; - - if (This->seektable && (duration / SEEK_INTERVAL) > last_entry) - { - if (last_entry + 1 > duration / SEEK_INTERVAL) - { - ERR("Somehow skipped %d interval lengths instead of 1\n", (DWORD)(duration/SEEK_INTERVAL) - (last_entry + 1)); - } - ++last_entry; - - TRACE("Entry: %u\n", last_entry); - if (last_entry >= This->seek_entries) - { - This->seek_entries += 64; - This->seektable = CoTaskMemRealloc(This->seektable, (This->seek_entries)*sizeof(struct seek_entry)); - } - This->seektable[last_entry].bytepos = pos; - This->seektable[last_entry].timepos = duration; - } - - TRACE("Pos: %x%08x/%x%08x\n", (DWORD)(pos >> 32), (DWORD)pos, (DWORD)(This->EndOfFile>>32), (DWORD)This->EndOfFile); - } - hr = S_OK; + duration = (This->EndOfFile-This->begin_offset) * 10000000 / format->nAvgBytesPerSec; TRACE("Duration: %d seconds\n", (DWORD)(duration / 10000000)); - TRACE("Parsing took %u ms\n", GetTickCount() - ticks); - This->duration = duration; - This->Parser.mediaSeeking.llCurrent = 0; - This->Parser.mediaSeeking.llDuration = duration; - This->Parser.mediaSeeking.llStop = duration; + This->Parser.sourceSeeking.llCurrent = 0; + This->Parser.sourceSeeking.llDuration = duration; + This->Parser.sourceSeeking.llStop = duration; break; } case MPEG_VIDEO_HEADER: @@ -618,80 +605,67 @@ static HRESULT MPEGSplitter_cleanup(LPVOID iface) return S_OK; } -static HRESULT MPEGSplitter_seek(IBaseFilter *iface) +static HRESULT WINAPI MPEGSplitter_seek(IMediaSeeking *iface) { - MPEGSplitterImpl *This = (MPEGSplitterImpl*)iface; + MPEGSplitterImpl *This = impl_from_IMediaSeeking(iface); PullPin *pPin = This->Parser.pInputPin; LONGLONG newpos, timepos, bytepos; - HRESULT hr = S_OK; + HRESULT hr = E_INVALIDARG; BYTE header[4]; - newpos = This->Parser.mediaSeeking.llCurrent; - - if (newpos > This->duration) - { - WARN("Requesting position %x%08x beyond end of stream %x%08x\n", (DWORD)(newpos>>32), (DWORD)newpos, (DWORD)(This->duration>>32), (DWORD)This->duration); - return E_INVALIDARG; - } - + newpos = This->Parser.sourceSeeking.llCurrent; if (This->position/1000000 == newpos/1000000) { TRACE("Requesting position %x%08x same as current position %x%08x\n", (DWORD)(newpos>>32), (DWORD)newpos, (DWORD)(This->position>>32), (DWORD)This->position); return S_OK; } - /* Position, cached */ - bytepos = This->seektable[newpos / SEEK_INTERVAL].bytepos; - timepos = This->seektable[newpos / SEEK_INTERVAL].timepos; - - hr = IAsyncReader_SyncRead(pPin->pReader, bytepos, 4, header); + bytepos = This->begin_offset; + timepos = 0; + /* http://mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm has a whole read up on audio headers */ while (bytepos + 3 < This->EndOfFile) { + LONGLONG duration = timepos; LONGLONG length = 0; hr = IAsyncReader_SyncRead(pPin->pReader, bytepos, 4, header); - if (hr != S_OK || timepos >= newpos) + if (hr != S_OK) break; - - while (parse_header(header, &length, &timepos) && bytepos + 3 < This->EndOfFile) + while ((hr=parse_header(header, &length, &duration)) != S_OK && + bytepos + 4 < This->EndOfFile) { /* No valid header yet; shift by a byte and check again */ memmove(header, header+1, 3); - hr = IAsyncReader_SyncRead(pPin->pReader, ++bytepos, 1, header + 3); + hr = IAsyncReader_SyncRead(pPin->pReader, ++bytepos + 3, 1, header + 3); if (hr != S_OK) break; - } - bytepos += length; - TRACE("Pos: %x%08x/%x%08x\n", (DWORD)(bytepos >> 32), (DWORD)bytepos, (DWORD)(This->EndOfFile>>32), (DWORD)This->EndOfFile); + } + if (hr != S_OK || duration > newpos) + break; + bytepos += length; + timepos = duration; } if (SUCCEEDED(hr)) { PullPin *pin = This->Parser.pInputPin; - IPin *victim = NULL; TRACE("Moving sound to %08u bytes!\n", (DWORD)bytepos); EnterCriticalSection(&pin->thread_lock); - IPin_BeginFlush((IPin *)pin); + IPin_BeginFlush(&pin->pin.IPin_iface); /* Make sure this is done while stopped, BeginFlush takes care of this */ - EnterCriticalSection(&This->Parser.csFilter); + EnterCriticalSection(&This->Parser.filter.csFilter); memcpy(This->header, header, 4); - IPin_ConnectedTo(This->Parser.ppPins[1], &victim); - if (victim) - { - IPin_NewSegment(victim, newpos, This->duration, pin->dRate); - IPin_Release(victim); - } pin->rtStart = pin->rtCurrent = MEDIATIME_FROM_BYTES(bytepos); pin->rtStop = MEDIATIME_FROM_BYTES((REFERENCE_TIME)This->EndOfFile); This->seek = TRUE; This->position = newpos; - LeaveCriticalSection(&This->Parser.csFilter); + LeaveCriticalSection(&This->Parser.filter.csFilter); TRACE("Done flushing\n"); - IPin_EndFlush((IPin *)pin); + IPin_EndFlush(&pin->pin.IPin_iface); LeaveCriticalSection(&pin->thread_lock); } return hr; @@ -712,7 +686,9 @@ static HRESULT MPEGSplitter_first_request(LPVOID iface) IMediaSample *sample; TRACE("Seeking? %d\n", This->seek); - assert(parse_header(This->header, &length, NULL) == S_OK); + + hr = parse_header(This->header, &length, NULL); + assert(hr == S_OK); if (pin->rtCurrent >= pin->rtStop) { @@ -735,15 +711,19 @@ static HRESULT MPEGSplitter_first_request(LPVOID iface) hr = IMediaSample_SetTime(sample, &rtSampleStart, &rtSampleStop); - pin->rtCurrent = pin->rtNext; - pin->rtNext = rtSampleStop; - IMediaSample_SetPreroll(sample, FALSE); - IMediaSample_SetDiscontinuity(sample, This->seek); + IMediaSample_SetDiscontinuity(sample, TRUE); IMediaSample_SetSyncPoint(sample, 1); This->seek = 0; hr = IAsyncReader_Request(pin->pReader, sample, 0); + if (SUCCEEDED(hr)) + { + pin->rtCurrent = pin->rtNext; + pin->rtNext = rtSampleStop; + } + else + IMediaSample_Release(sample); } if (FAILED(hr)) ERR("Horsemen of the apocalypse came to bring error 0x%08x\n", hr); @@ -787,14 +767,6 @@ HRESULT MPEGSplitter_create(IUnknown * pUnkOuter, LPVOID * ppv) return E_OUTOFMEMORY; ZeroMemory(This, sizeof(MPEGSplitterImpl)); - This->seektable = CoTaskMemAlloc(sizeof(struct seek_entry) * 64); - if (!This->seektable) - { - CoTaskMemFree(This); - return E_OUTOFMEMORY; - } - This->seek_entries = 64; - hr = Parser_Create(&(This->Parser), &MPEGSplitter_Vtbl, &CLSID_MPEG1Splitter, MPEGSplitter_process_sample, MPEGSplitter_query_accept, MPEGSplitter_pre_connect, MPEGSplitter_cleanup, MPEGSplitter_disconnect, MPEGSplitter_first_request, NULL, NULL, MPEGSplitter_seek, NULL); if (FAILED(hr)) { diff --git a/reactos/dll/directx/quartz/nullrenderer.c b/reactos/dll/directx/quartz/nullrenderer.c index 1c4311ec40b..af8c48ec39a 100644 --- a/reactos/dll/directx/quartz/nullrenderer.c +++ b/reactos/dll/directx/quartz/nullrenderer.c @@ -24,7 +24,6 @@ #define NONAMELESSSTRUCT #define NONAMELESSUNION #include "quartz_private.h" -#include "control_private.h" #include "pin.h" //#include "uuids.h" @@ -42,181 +41,75 @@ WINE_DEFAULT_DEBUG_CHANNEL(quartz); -static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0}; -static const WCHAR wcsAltInputPinName[] = {'I','n',0}; - -static const IBaseFilterVtbl NullRenderer_Vtbl; -static const IUnknownVtbl IInner_VTable; -static const IPinVtbl NullRenderer_InputPin_Vtbl; - typedef struct NullRendererImpl { - const IBaseFilterVtbl * lpVtbl; - const IUnknownVtbl * IInner_vtbl; - - LONG refCount; - CRITICAL_SECTION csFilter; - FILTER_STATE state; - REFERENCE_TIME rtStreamStart; - IReferenceClock * pClock; - FILTER_INFO filterInfo; - - InputPin *pInputPin; - IUnknown * pUnkOuter; - BOOL bUnkOuterValid; - BOOL bAggregatable; - MediaSeekingImpl mediaSeeking; + BaseRenderer renderer; + IUnknown IUnknown_inner; + IAMFilterMiscFlags IAMFilterMiscFlags_iface; + IUnknown *outer_unk; } NullRendererImpl; -static HRESULT NullRenderer_Sample(LPVOID iface, IMediaSample * pSample) +static HRESULT WINAPI NullRenderer_DoRenderSample(BaseRenderer *iface, IMediaSample *pMediaSample) { - NullRendererImpl *This = iface; - HRESULT hr = S_OK; - - TRACE("%p %p\n", iface, pSample); - - EnterCriticalSection(&This->csFilter); - if (This->pInputPin->flushing || This->pInputPin->end_of_stream) - hr = S_FALSE; - LeaveCriticalSection(&This->csFilter); - - return hr; + return S_OK; } -static HRESULT NullRenderer_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt) +static HRESULT WINAPI NullRenderer_CheckMediaType(BaseRenderer *iface, const AM_MEDIA_TYPE * pmt) { TRACE("Not a stub!\n"); return S_OK; } -static inline NullRendererImpl *impl_from_IMediaSeeking( IMediaSeeking *iface ) -{ - return (NullRendererImpl *)((char*)iface - FIELD_OFFSET(NullRendererImpl, mediaSeeking.lpVtbl)); -} - -static HRESULT WINAPI NullRendererImpl_Seeking_QueryInterface(IMediaSeeking * iface, REFIID riid, LPVOID * ppv) -{ - NullRendererImpl *This = impl_from_IMediaSeeking(iface); - - return IUnknown_QueryInterface((IUnknown *)This, riid, ppv); -} - -static ULONG WINAPI NullRendererImpl_Seeking_AddRef(IMediaSeeking * iface) -{ - NullRendererImpl *This = impl_from_IMediaSeeking(iface); - - return IUnknown_AddRef((IUnknown *)This); -} - -static ULONG WINAPI NullRendererImpl_Seeking_Release(IMediaSeeking * iface) -{ - NullRendererImpl *This = impl_from_IMediaSeeking(iface); - - return IUnknown_Release((IUnknown *)This); -} - -static const IMediaSeekingVtbl TransformFilter_Seeking_Vtbl = -{ - NullRendererImpl_Seeking_QueryInterface, - NullRendererImpl_Seeking_AddRef, - NullRendererImpl_Seeking_Release, - MediaSeekingImpl_GetCapabilities, - MediaSeekingImpl_CheckCapabilities, - MediaSeekingImpl_IsFormatSupported, - MediaSeekingImpl_QueryPreferredFormat, - MediaSeekingImpl_GetTimeFormat, - MediaSeekingImpl_IsUsingTimeFormat, - MediaSeekingImpl_SetTimeFormat, - MediaSeekingImpl_GetDuration, - MediaSeekingImpl_GetStopPosition, - MediaSeekingImpl_GetCurrentPosition, - MediaSeekingImpl_ConvertTimeFormat, - MediaSeekingImpl_SetPositions, - MediaSeekingImpl_GetPositions, - MediaSeekingImpl_GetAvailable, - MediaSeekingImpl_SetRate, - MediaSeekingImpl_GetRate, - MediaSeekingImpl_GetPreroll +static const BaseRendererFuncTable RendererFuncTable = { + NullRenderer_CheckMediaType, + NullRenderer_DoRenderSample, + /**/ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + /**/ + NULL, + NULL, + NULL, + NULL, + NULL, }; -static HRESULT NullRendererImpl_Change(IBaseFilter *iface) +static inline NullRendererImpl *impl_from_IUnknown(IUnknown *iface) { - TRACE("(%p)\n", iface); - return S_OK; + return CONTAINING_RECORD(iface, NullRendererImpl, IUnknown_inner); } -HRESULT NullRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv) +static HRESULT WINAPI NullRendererInner_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) { - HRESULT hr; - PIN_INFO piInput; - NullRendererImpl * pNullRenderer; + NullRendererImpl *This = impl_from_IUnknown(iface); - TRACE("(%p, %p)\n", pUnkOuter, ppv); - - *ppv = NULL; - - pNullRenderer = CoTaskMemAlloc(sizeof(NullRendererImpl)); - pNullRenderer->pUnkOuter = pUnkOuter; - pNullRenderer->bUnkOuterValid = FALSE; - pNullRenderer->bAggregatable = FALSE; - pNullRenderer->IInner_vtbl = &IInner_VTable; - - pNullRenderer->lpVtbl = &NullRenderer_Vtbl; - pNullRenderer->refCount = 1; - InitializeCriticalSection(&pNullRenderer->csFilter); - pNullRenderer->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": NullRendererImpl.csFilter"); - pNullRenderer->state = State_Stopped; - pNullRenderer->pClock = NULL; - ZeroMemory(&pNullRenderer->filterInfo, sizeof(FILTER_INFO)); - - /* construct input pin */ - piInput.dir = PINDIR_INPUT; - piInput.pFilter = (IBaseFilter *)pNullRenderer; - lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0])); - - hr = InputPin_Construct(&NullRenderer_InputPin_Vtbl, &piInput, NullRenderer_Sample, (LPVOID)pNullRenderer, NullRenderer_QueryAccept, NULL, &pNullRenderer->csFilter, NULL, (IPin **)&pNullRenderer->pInputPin); - - if (SUCCEEDED(hr)) - { - MediaSeekingImpl_Init((IBaseFilter*)pNullRenderer, NullRendererImpl_Change, NullRendererImpl_Change, NullRendererImpl_Change, &pNullRenderer->mediaSeeking, &pNullRenderer->csFilter); - pNullRenderer->mediaSeeking.lpVtbl = &TransformFilter_Seeking_Vtbl; - - *ppv = pNullRenderer; - } - else - { - pNullRenderer->csFilter.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&pNullRenderer->csFilter); - CoTaskMemFree(pNullRenderer); - } - - return hr; -} - -static HRESULT WINAPI NullRendererInner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv) -{ - ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface); TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv); - if (This->bAggregatable) - This->bUnkOuterValid = TRUE; - *ppv = NULL; if (IsEqualIID(riid, &IID_IUnknown)) - *ppv = &This->IInner_vtbl; - else if (IsEqualIID(riid, &IID_IPersist)) - *ppv = This; - else if (IsEqualIID(riid, &IID_IMediaFilter)) - *ppv = This; - else if (IsEqualIID(riid, &IID_IBaseFilter)) - *ppv = This; - else if (IsEqualIID(riid, &IID_IMediaSeeking)) - *ppv = &This->mediaSeeking; + *ppv = &This->IUnknown_inner; + else if (IsEqualIID(riid, &IID_IAMFilterMiscFlags)) + *ppv = &This->IAMFilterMiscFlags_iface; + else + { + HRESULT hr; + hr = BaseRendererImpl_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv); + if (SUCCEEDED(hr)) + return hr; + } if (*ppv) { - IUnknown_AddRef((IUnknown *)(*ppv)); + IUnknown_AddRef((IUnknown *)*ppv); return S_OK; } @@ -226,49 +119,24 @@ static HRESULT WINAPI NullRendererInner_QueryInterface(IUnknown * iface, REFIID return E_NOINTERFACE; } -static ULONG WINAPI NullRendererInner_AddRef(IUnknown * iface) +static ULONG WINAPI NullRendererInner_AddRef(IUnknown *iface) { - ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface); - ULONG refCount = InterlockedIncrement(&This->refCount); - - TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1); - - return refCount; + NullRendererImpl *This = impl_from_IUnknown(iface); + return BaseFilterImpl_AddRef(&This->renderer.filter.IBaseFilter_iface); } -static ULONG WINAPI NullRendererInner_Release(IUnknown * iface) +static ULONG WINAPI NullRendererInner_Release(IUnknown *iface) { - ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface); - ULONG refCount = InterlockedDecrement(&This->refCount); - - TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1); + NullRendererImpl *This = impl_from_IUnknown(iface); + ULONG refCount = BaseFilterImpl_Release(&This->renderer.filter.IBaseFilter_iface); if (!refCount) { - IPin *pConnectedTo; - - if (This->pClock) - IReferenceClock_Release(This->pClock); - - if (SUCCEEDED(IPin_ConnectedTo((IPin *)This->pInputPin, &pConnectedTo))) - { - IPin_Disconnect(pConnectedTo); - IPin_Release(pConnectedTo); - } - IPin_Disconnect((IPin *)This->pInputPin); - IPin_Release((IPin *)This->pInputPin); - - This->lpVtbl = NULL; - - This->csFilter.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&This->csFilter); - TRACE("Destroying Null Renderer\n"); CoTaskMemFree(This); - return 0; } - else - return refCount; + + return refCount; } static const IUnknownVtbl IInner_VTable = @@ -278,253 +146,27 @@ static const IUnknownVtbl IInner_VTable = NullRendererInner_Release }; +static inline NullRendererImpl *impl_from_IBaseFilter(IBaseFilter *iface) +{ + return CONTAINING_RECORD(iface, NullRendererImpl, renderer.filter.IBaseFilter_iface); +} + static HRESULT WINAPI NullRenderer_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv) { - NullRendererImpl *This = (NullRendererImpl *)iface; - - if (This->bAggregatable) - This->bUnkOuterValid = TRUE; - - if (This->pUnkOuter) - { - if (This->bAggregatable) - return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv); - - if (IsEqualIID(riid, &IID_IUnknown)) - { - HRESULT hr; - - IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl)); - hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv); - IUnknown_Release((IUnknown *)&(This->IInner_vtbl)); - This->bAggregatable = TRUE; - return hr; - } - - *ppv = NULL; - return E_NOINTERFACE; - } - - return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv); + NullRendererImpl *This = impl_from_IBaseFilter(iface); + return IUnknown_QueryInterface(This->outer_unk, riid, ppv); } static ULONG WINAPI NullRenderer_AddRef(IBaseFilter * iface) { - NullRendererImpl *This = (NullRendererImpl *)iface; - - if (This->pUnkOuter && This->bUnkOuterValid) - return IUnknown_AddRef(This->pUnkOuter); - return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl)); + NullRendererImpl *This = impl_from_IBaseFilter(iface); + return IUnknown_AddRef(This->outer_unk); } static ULONG WINAPI NullRenderer_Release(IBaseFilter * iface) { - NullRendererImpl *This = (NullRendererImpl *)iface; - - if (This->pUnkOuter && This->bUnkOuterValid) - return IUnknown_Release(This->pUnkOuter); - return IUnknown_Release((IUnknown *)&(This->IInner_vtbl)); -} - -/** IPersist methods **/ - -static HRESULT WINAPI NullRenderer_GetClassID(IBaseFilter * iface, CLSID * pClsid) -{ - NullRendererImpl *This = (NullRendererImpl *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, pClsid); - - *pClsid = CLSID_NullRenderer; - - return S_OK; -} - -/** IMediaFilter methods **/ - -static HRESULT WINAPI NullRenderer_Stop(IBaseFilter * iface) -{ - NullRendererImpl *This = (NullRendererImpl *)iface; - - TRACE("(%p/%p)->()\n", This, iface); - - EnterCriticalSection(&This->csFilter); - { - This->state = State_Stopped; - } - LeaveCriticalSection(&This->csFilter); - - return S_OK; -} - -static HRESULT WINAPI NullRenderer_Pause(IBaseFilter * iface) -{ - NullRendererImpl *This = (NullRendererImpl *)iface; - - TRACE("(%p/%p)->()\n", This, iface); - - EnterCriticalSection(&This->csFilter); - { - if (This->state == State_Stopped) - This->pInputPin->end_of_stream = 0; - This->state = State_Paused; - } - LeaveCriticalSection(&This->csFilter); - - return S_OK; -} - -static HRESULT WINAPI NullRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tStart) -{ - NullRendererImpl *This = (NullRendererImpl *)iface; - - TRACE("(%p/%p)->(%s)\n", This, iface, wine_dbgstr_longlong(tStart)); - - EnterCriticalSection(&This->csFilter); - { - This->rtStreamStart = tStart; - This->state = State_Running; - This->pInputPin->end_of_stream = 0; - } - LeaveCriticalSection(&This->csFilter); - - return S_OK; -} - -static HRESULT WINAPI NullRenderer_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState) -{ - NullRendererImpl *This = (NullRendererImpl *)iface; - - TRACE("(%p/%p)->(%d, %p)\n", This, iface, dwMilliSecsTimeout, pState); - - EnterCriticalSection(&This->csFilter); - { - *pState = This->state; - } - LeaveCriticalSection(&This->csFilter); - - return S_OK; -} - -static HRESULT WINAPI NullRenderer_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock) -{ - NullRendererImpl *This = (NullRendererImpl *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, pClock); - - EnterCriticalSection(&This->csFilter); - { - if (This->pClock) - IReferenceClock_Release(This->pClock); - This->pClock = pClock; - if (This->pClock) - IReferenceClock_AddRef(This->pClock); - } - LeaveCriticalSection(&This->csFilter); - - return S_OK; -} - -static HRESULT WINAPI NullRenderer_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock) -{ - NullRendererImpl *This = (NullRendererImpl *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, ppClock); - - EnterCriticalSection(&This->csFilter); - { - *ppClock = This->pClock; - if (This->pClock) - IReferenceClock_AddRef(This->pClock); - } - LeaveCriticalSection(&This->csFilter); - - return S_OK; -} - -/** IBaseFilter implementation **/ - -static HRESULT NullRenderer_GetPin(IBaseFilter *iface, ULONG pos, IPin **pin, DWORD *lastsynctick) -{ - NullRendererImpl *This = (NullRendererImpl *)iface; - - /* Our pins are static, not changing so setting static tick count is ok */ - *lastsynctick = 0; - - if (pos >= 1) - return S_FALSE; - - *pin = (IPin *)This->pInputPin; - IPin_AddRef(*pin); - return S_OK; -} - -static HRESULT WINAPI NullRenderer_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum) -{ - NullRendererImpl *This = (NullRendererImpl *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum); - - return IEnumPinsImpl_Construct(ppEnum, NullRenderer_GetPin, iface); -} - -static HRESULT WINAPI NullRenderer_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin) -{ - NullRendererImpl *This = (NullRendererImpl *)iface; - - TRACE("(%p/%p)->(%p,%p)\n", This, iface, debugstr_w(Id), ppPin); - - if (!Id || !ppPin) - return E_POINTER; - - if (!lstrcmpiW(Id,wcsInputPinName) || !lstrcmpiW(Id,wcsAltInputPinName)) - { - *ppPin = (IPin *)This->pInputPin; - IPin_AddRef(*ppPin); - return S_OK; - } - *ppPin = NULL; - return VFW_E_NOT_FOUND; -} - -static HRESULT WINAPI NullRenderer_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo) -{ - NullRendererImpl *This = (NullRendererImpl *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, pInfo); - - strcpyW(pInfo->achName, This->filterInfo.achName); - pInfo->pGraph = This->filterInfo.pGraph; - - if (pInfo->pGraph) - IFilterGraph_AddRef(pInfo->pGraph); - - return S_OK; -} - -static HRESULT WINAPI NullRenderer_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName) -{ - NullRendererImpl *This = (NullRendererImpl *)iface; - - TRACE("(%p/%p)->(%p, %s)\n", This, iface, pGraph, debugstr_w(pName)); - - EnterCriticalSection(&This->csFilter); - { - if (pName) - strcpyW(This->filterInfo.achName, pName); - else - *This->filterInfo.achName = '\0'; - This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */ - } - LeaveCriticalSection(&This->csFilter); - - return S_OK; -} - -static HRESULT WINAPI NullRenderer_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo) -{ - NullRendererImpl *This = (NullRendererImpl *)iface; - TRACE("(%p/%p)->(%p)\n", This, iface, pVendorInfo); - return E_NOTIMPL; + NullRendererImpl *This = impl_from_IBaseFilter(iface); + return IUnknown_Release(This->outer_unk); } static const IBaseFilterVtbl NullRenderer_Vtbl = @@ -532,62 +174,85 @@ static const IBaseFilterVtbl NullRenderer_Vtbl = NullRenderer_QueryInterface, NullRenderer_AddRef, NullRenderer_Release, - NullRenderer_GetClassID, - NullRenderer_Stop, - NullRenderer_Pause, - NullRenderer_Run, - NullRenderer_GetState, - NullRenderer_SetSyncSource, - NullRenderer_GetSyncSource, - NullRenderer_EnumPins, - NullRenderer_FindPin, - NullRenderer_QueryFilterInfo, - NullRenderer_JoinFilterGraph, - NullRenderer_QueryVendorInfo + BaseFilterImpl_GetClassID, + BaseRendererImpl_Stop, + BaseRendererImpl_Pause, + BaseRendererImpl_Run, + BaseRendererImpl_GetState, + BaseRendererImpl_SetSyncSource, + BaseFilterImpl_GetSyncSource, + BaseFilterImpl_EnumPins, + BaseRendererImpl_FindPin, + BaseFilterImpl_QueryFilterInfo, + BaseFilterImpl_JoinFilterGraph, + BaseFilterImpl_QueryVendorInfo }; -static HRESULT WINAPI NullRenderer_InputPin_EndOfStream(IPin * iface) +static NullRendererImpl *impl_from_IAMFilterMiscFlags(IAMFilterMiscFlags *iface) { - InputPin* This = (InputPin*)iface; - IMediaEventSink* pEventSink; - IFilterGraph *graph; - HRESULT hr = S_OK; - - TRACE("(%p/%p)->()\n", This, iface); - - InputPin_EndOfStream(iface); - graph = ((NullRendererImpl*)This->pin.pinInfo.pFilter)->filterInfo.pGraph; - if (graph) - { - hr = IFilterGraph_QueryInterface(((NullRendererImpl*)This->pin.pinInfo.pFilter)->filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink); - if (SUCCEEDED(hr)) - { - hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, 0); - IMediaEventSink_Release(pEventSink); - } - } - - return hr; + return CONTAINING_RECORD(iface, NullRendererImpl, IAMFilterMiscFlags_iface); } -static const IPinVtbl NullRenderer_InputPin_Vtbl = +static HRESULT WINAPI AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid, + void **ppv) { - InputPin_QueryInterface, - IPinImpl_AddRef, - InputPin_Release, - InputPin_Connect, - InputPin_ReceiveConnection, - IPinImpl_Disconnect, - IPinImpl_ConnectedTo, - IPinImpl_ConnectionMediaType, - IPinImpl_QueryPinInfo, - IPinImpl_QueryDirection, - IPinImpl_QueryId, - IPinImpl_QueryAccept, - IPinImpl_EnumMediaTypes, - IPinImpl_QueryInternalConnections, - NullRenderer_InputPin_EndOfStream, - InputPin_BeginFlush, - InputPin_EndFlush, - InputPin_NewSegment + NullRendererImpl *This = impl_from_IAMFilterMiscFlags(iface); + return IUnknown_QueryInterface(This->outer_unk, riid, ppv); +} + +static ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface) +{ + NullRendererImpl *This = impl_from_IAMFilterMiscFlags(iface); + return IUnknown_AddRef(This->outer_unk); +} + +static ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface) +{ + NullRendererImpl *This = impl_from_IAMFilterMiscFlags(iface); + return IUnknown_Release(This->outer_unk); +} + +static ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface) +{ + return AM_FILTER_MISC_FLAGS_IS_RENDERER; +} + +static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = { + AMFilterMiscFlags_QueryInterface, + AMFilterMiscFlags_AddRef, + AMFilterMiscFlags_Release, + AMFilterMiscFlags_GetMiscFlags }; + +HRESULT NullRenderer_create(IUnknown *pUnkOuter, void **ppv) +{ + HRESULT hr; + NullRendererImpl *pNullRenderer; + + TRACE("(%p, %p)\n", pUnkOuter, ppv); + + *ppv = NULL; + + pNullRenderer = CoTaskMemAlloc(sizeof(NullRendererImpl)); + pNullRenderer->IUnknown_inner.lpVtbl = &IInner_VTable; + pNullRenderer->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_Vtbl; + + if (pUnkOuter) + pNullRenderer->outer_unk = pUnkOuter; + else + pNullRenderer->outer_unk = &pNullRenderer->IUnknown_inner; + + hr = BaseRenderer_Init(&pNullRenderer->renderer, &NullRenderer_Vtbl, pUnkOuter, + &CLSID_NullRenderer, (DWORD_PTR)(__FILE__ ": NullRendererImpl.csFilter"), + &RendererFuncTable); + + if (FAILED(hr)) + { + BaseRendererImpl_Release(&pNullRenderer->renderer.filter.IBaseFilter_iface); + CoTaskMemFree(pNullRenderer); + } + else + *ppv = &pNullRenderer->IUnknown_inner; + + return S_OK; +} diff --git a/reactos/dll/directx/quartz/parser.c b/reactos/dll/directx/quartz/parser.c index 8fb591d2972..0d731011592 100644 --- a/reactos/dll/directx/quartz/parser.c +++ b/reactos/dll/directx/quartz/parser.c @@ -20,7 +20,6 @@ */ #include "quartz_private.h" -#include "control_private.h" #include "pin.h" //#include "vfwmsgs.h" @@ -41,44 +40,76 @@ static const IMediaSeekingVtbl Parser_Seeking_Vtbl; static const IPinVtbl Parser_OutputPin_Vtbl; static const IPinVtbl Parser_InputPin_Vtbl; -static HRESULT Parser_OutputPin_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt); -static HRESULT Parser_ChangeCurrent(IBaseFilter *iface); -static HRESULT Parser_ChangeStop(IBaseFilter *iface); -static HRESULT Parser_ChangeRate(IBaseFilter *iface); +static HRESULT WINAPI Parser_ChangeStart(IMediaSeeking *iface); +static HRESULT WINAPI Parser_ChangeStop(IMediaSeeking *iface); +static HRESULT WINAPI Parser_ChangeRate(IMediaSeeking *iface); +static HRESULT WINAPI Parser_OutputPin_DecideBufferSize(BaseOutputPin *iface, IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest); +static HRESULT WINAPI Parser_OutputPin_GetMediaType(BasePin *iface, int iPosition, AM_MEDIA_TYPE *pmt); +static HRESULT WINAPI Parser_OutputPin_DecideAllocator(BaseOutputPin *This, IMemInputPin *pPin, IMemAllocator **pAlloc); +static HRESULT WINAPI Parser_OutputPin_BreakConnect(BaseOutputPin *This); static inline ParserImpl *impl_from_IMediaSeeking( IMediaSeeking *iface ) { - return (ParserImpl *)((char*)iface - FIELD_OFFSET(ParserImpl, mediaSeeking.lpVtbl)); + return CONTAINING_RECORD(iface, ParserImpl, sourceSeeking.IMediaSeeking_iface); } +static inline ParserImpl *impl_from_IBaseFilter( IBaseFilter *iface ) +{ + return CONTAINING_RECORD(iface, ParserImpl, filter.IBaseFilter_iface); +} -HRESULT Parser_Create(ParserImpl* pParser, const IBaseFilterVtbl *Parser_Vtbl, const CLSID* pClsid, PFN_PROCESS_SAMPLE fnProcessSample, PFN_QUERY_ACCEPT fnQueryAccept, PFN_PRE_CONNECT fnPreConnect, PFN_CLEANUP fnCleanup, PFN_DISCONNECT fnDisconnect, REQUESTPROC fnRequest, STOPPROCESSPROC fnDone, CHANGEPROC stop, CHANGEPROC current, CHANGEPROC rate) +static inline ParserImpl *impl_from_BaseFilter( BaseFilter *iface ) +{ + return CONTAINING_RECORD(iface, ParserImpl, filter); +} + +/* FIXME: WRONG */ +static IPin* WINAPI Parser_GetPin(BaseFilter *iface, int pos) +{ + ParserImpl *This = impl_from_BaseFilter(iface); + + TRACE("Asking for pos %x\n", pos); + + /* Input pin also has a pin, hence the > and not >= */ + if (pos > This->cStreams || pos < 0) + return NULL; + + IPin_AddRef(This->ppPins[pos]); + return This->ppPins[pos]; +} + +static LONG WINAPI Parser_GetPinCount(BaseFilter *iface) +{ + ParserImpl *This = impl_from_BaseFilter(iface); + + return This->cStreams; +} + +static const BaseFilterFuncTable BaseFuncTable = { + Parser_GetPin, + Parser_GetPinCount +}; + +HRESULT Parser_Create(ParserImpl* pParser, const IBaseFilterVtbl *Parser_Vtbl, const CLSID* pClsid, PFN_PROCESS_SAMPLE fnProcessSample, PFN_QUERY_ACCEPT fnQueryAccept, PFN_PRE_CONNECT fnPreConnect, PFN_CLEANUP fnCleanup, PFN_DISCONNECT fnDisconnect, REQUESTPROC fnRequest, STOPPROCESSPROC fnDone, SourceSeeking_ChangeStop stop, SourceSeeking_ChangeStart start, SourceSeeking_ChangeRate rate) { HRESULT hr; PIN_INFO piInput; /* pTransformFilter is already allocated */ - pParser->clsid = *pClsid; - pParser->lpVtbl = Parser_Vtbl; - pParser->refCount = 1; - InitializeCriticalSection(&pParser->csFilter); - pParser->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ParserImpl.csFilter"); - pParser->state = State_Stopped; - pParser->pClock = NULL; + BaseFilter_Init(&pParser->filter, Parser_Vtbl, pClsid, (DWORD_PTR)(__FILE__ ": ParserImpl.csFilter"), &BaseFuncTable); + pParser->fnDisconnect = fnDisconnect; - ZeroMemory(&pParser->filterInfo, sizeof(FILTER_INFO)); - pParser->lastpinchange = GetTickCount(); pParser->cStreams = 0; pParser->ppPins = CoTaskMemAlloc(1 * sizeof(IPin *)); /* construct input pin */ piInput.dir = PINDIR_INPUT; - piInput.pFilter = (IBaseFilter *)pParser; + piInput.pFilter = &pParser->filter.IBaseFilter_iface; lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0])); - if (!current) - current = Parser_ChangeCurrent; + if (!start) + start = Parser_ChangeStart; if (!stop) stop = Parser_ChangeStop; @@ -86,21 +117,19 @@ HRESULT Parser_Create(ParserImpl* pParser, const IBaseFilterVtbl *Parser_Vtbl, c if (!rate) rate = Parser_ChangeRate; - MediaSeekingImpl_Init((IBaseFilter*)pParser, stop, current, rate, &pParser->mediaSeeking, &pParser->csFilter); - pParser->mediaSeeking.lpVtbl = &Parser_Seeking_Vtbl; + SourceSeeking_Init(&pParser->sourceSeeking, &Parser_Seeking_Vtbl, stop, start, rate, &pParser->filter.csFilter); - hr = PullPin_Construct(&Parser_InputPin_Vtbl, &piInput, fnProcessSample, (LPVOID)pParser, fnQueryAccept, fnCleanup, fnRequest, fnDone, &pParser->csFilter, (IPin **)&pParser->pInputPin); + hr = PullPin_Construct(&Parser_InputPin_Vtbl, &piInput, fnProcessSample, (LPVOID)pParser, fnQueryAccept, fnCleanup, fnRequest, fnDone, &pParser->filter.csFilter, (IPin **)&pParser->pInputPin); if (SUCCEEDED(hr)) { - pParser->ppPins[0] = (IPin *)pParser->pInputPin; + pParser->ppPins[0] = &pParser->pInputPin->pin.IPin_iface; pParser->pInputPin->fnPreConnect = fnPreConnect; } else { CoTaskMemFree(pParser->ppPins); - pParser->csFilter.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&pParser->csFilter); + BaseFilterImpl_Release(&pParser->filter.IBaseFilter_iface); CoTaskMemFree(pParser); } @@ -109,21 +138,16 @@ HRESULT Parser_Create(ParserImpl* pParser, const IBaseFilterVtbl *Parser_Vtbl, c HRESULT WINAPI Parser_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv) { - ParserImpl *This = (ParserImpl *)iface; + ParserImpl *This = impl_from_IBaseFilter(iface); TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv); *ppv = NULL; - if (IsEqualIID(riid, &IID_IUnknown)) + if ( IsEqualIID(riid, &IID_IUnknown) + || IsEqualIID(riid, &IID_IPersist) + || IsEqualIID(riid, &IID_IMediaFilter) + || IsEqualIID(riid, &IID_IBaseFilter) ) *ppv = This; - else if (IsEqualIID(riid, &IID_IPersist)) - *ppv = This; - else if (IsEqualIID(riid, &IID_IMediaFilter)) - *ppv = This; - else if (IsEqualIID(riid, &IID_IBaseFilter)) - *ppv = This; - else if (IsEqualIID(riid, &IID_IMediaSeeking)) - *ppv = &This->mediaSeeking; if (*ppv) { @@ -139,12 +163,7 @@ HRESULT WINAPI Parser_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ULONG WINAPI Parser_AddRef(IBaseFilter * iface) { - ParserImpl *This = (ParserImpl *)iface; - ULONG refCount = InterlockedIncrement(&This->refCount); - - TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1); - - return refCount; + return BaseFilterImpl_AddRef(iface); } void Parser_Destroy(ParserImpl *This) @@ -152,21 +171,18 @@ void Parser_Destroy(ParserImpl *This) IPin *connected = NULL; ULONG pinref; - assert(!This->refCount); + assert(!This->filter.refCount); PullPin_WaitForStateChange(This->pInputPin, INFINITE); - if (This->pClock) - IReferenceClock_Release(This->pClock); - /* Don't need to clean up output pins, freeing input pin will do that */ - IPin_ConnectedTo((IPin *)This->pInputPin, &connected); + IPin_ConnectedTo(&This->pInputPin->pin.IPin_iface, &connected); if (connected) { assert(IPin_Disconnect(connected) == S_OK); IPin_Release(connected); - assert(IPin_Disconnect((IPin *)This->pInputPin) == S_OK); + assert(IPin_Disconnect(&This->pInputPin->pin.IPin_iface) == S_OK); } - pinref = IPin_Release((IPin *)This->pInputPin); + pinref = IPin_Release(&This->pInputPin->pin.IPin_iface); if (pinref) { /* Valgrind could find this, if I kill it here */ @@ -174,14 +190,10 @@ void Parser_Destroy(ParserImpl *This) assert((LONG)pinref > 0); while (pinref) - pinref = IPin_Release((IPin *)This->pInputPin); + pinref = IPin_Release(&This->pInputPin->pin.IPin_iface); } CoTaskMemFree(This->ppPins); - This->lpVtbl = NULL; - - This->csFilter.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&This->csFilter); TRACE("Destroying parser\n"); CoTaskMemFree(This); @@ -189,8 +201,8 @@ void Parser_Destroy(ParserImpl *This) ULONG WINAPI Parser_Release(IBaseFilter * iface) { - ParserImpl *This = (ParserImpl *)iface; - ULONG refCount = InterlockedDecrement(&This->refCount); + ParserImpl *This = impl_from_IBaseFilter(iface); + ULONG refCount = BaseFilterImpl_Release(iface); TRACE("(%p)->() Release from %d\n", This, refCount + 1); @@ -204,11 +216,11 @@ ULONG WINAPI Parser_Release(IBaseFilter * iface) HRESULT WINAPI Parser_GetClassID(IBaseFilter * iface, CLSID * pClsid) { - ParserImpl *This = (ParserImpl *)iface; + ParserImpl *This = impl_from_IBaseFilter(iface); TRACE("(%p)\n", pClsid); - *pClsid = This->clsid; + *pClsid = This->filter.clsid; return S_OK; } @@ -217,8 +229,8 @@ HRESULT WINAPI Parser_GetClassID(IBaseFilter * iface, CLSID * pClsid) HRESULT WINAPI Parser_Stop(IBaseFilter * iface) { - ParserImpl *This = (ParserImpl *)iface; - PullPin *pin = (PullPin *)This->ppPins[0]; + ParserImpl *This = impl_from_IBaseFilter(iface); + PullPin *pin = impl_PullPin_from_IPin(This->ppPins[0]); ULONG i; TRACE("()\n"); @@ -226,24 +238,24 @@ HRESULT WINAPI Parser_Stop(IBaseFilter * iface) EnterCriticalSection(&pin->thread_lock); IAsyncReader_BeginFlush(This->pInputPin->pReader); - EnterCriticalSection(&This->csFilter); + EnterCriticalSection(&This->filter.csFilter); - if (This->state == State_Stopped) + if (This->filter.state == State_Stopped) { - LeaveCriticalSection(&This->csFilter); + LeaveCriticalSection(&This->filter.csFilter); IAsyncReader_EndFlush(This->pInputPin->pReader); LeaveCriticalSection(&pin->thread_lock); return S_OK; } - This->state = State_Stopped; + This->filter.state = State_Stopped; for (i = 1; i < (This->cStreams + 1); i++) { - OutputPin_DecommitAllocator((OutputPin *)This->ppPins[i]); + BaseOutputPinImpl_Inactive((BaseOutputPin *)This->ppPins[i]); } - LeaveCriticalSection(&This->csFilter); + LeaveCriticalSection(&This->filter.csFilter); PullPin_PauseProcessing(This->pInputPin); PullPin_WaitForStateChange(This->pInputPin, INFINITE); @@ -256,32 +268,32 @@ HRESULT WINAPI Parser_Stop(IBaseFilter * iface) HRESULT WINAPI Parser_Pause(IBaseFilter * iface) { HRESULT hr = S_OK; - ParserImpl *This = (ParserImpl *)iface; - PullPin *pin = (PullPin *)This->ppPins[0]; + ParserImpl *This = impl_from_IBaseFilter(iface); + PullPin *pin = impl_PullPin_from_IPin(This->ppPins[0]); TRACE("()\n"); EnterCriticalSection(&pin->thread_lock); - EnterCriticalSection(&This->csFilter); + EnterCriticalSection(&This->filter.csFilter); - if (This->state == State_Paused) + if (This->filter.state == State_Paused) { - LeaveCriticalSection(&This->csFilter); + LeaveCriticalSection(&This->filter.csFilter); LeaveCriticalSection(&pin->thread_lock); return S_OK; } - if (This->state == State_Stopped) + if (This->filter.state == State_Stopped) { - LeaveCriticalSection(&This->csFilter); + LeaveCriticalSection(&This->filter.csFilter); hr = IBaseFilter_Run(iface, -1); - EnterCriticalSection(&This->csFilter); + EnterCriticalSection(&This->filter.csFilter); } if (SUCCEEDED(hr)) - This->state = State_Paused; + This->filter.state = State_Paused; - LeaveCriticalSection(&This->csFilter); + LeaveCriticalSection(&This->filter.csFilter); LeaveCriticalSection(&pin->thread_lock); return hr; @@ -290,31 +302,30 @@ HRESULT WINAPI Parser_Pause(IBaseFilter * iface) HRESULT WINAPI Parser_Run(IBaseFilter * iface, REFERENCE_TIME tStart) { HRESULT hr = S_OK; - ParserImpl *This = (ParserImpl *)iface; - PullPin *pin = (PullPin *)This->ppPins[0]; + ParserImpl *This = impl_from_IBaseFilter(iface); + PullPin *pin = impl_PullPin_from_IPin(This->ppPins[0]); ULONG i; TRACE("(%s)\n", wine_dbgstr_longlong(tStart)); EnterCriticalSection(&pin->thread_lock); - EnterCriticalSection(&This->csFilter); + EnterCriticalSection(&This->filter.csFilter); { HRESULT hr_any = VFW_E_NOT_CONNECTED; - if (This->state == State_Running || This->state == State_Paused) + This->filter.rtStreamStart = tStart; + if (This->filter.state == State_Running || This->filter.state == State_Paused) { - This->state = State_Running; - LeaveCriticalSection(&This->csFilter); + This->filter.state = State_Running; + LeaveCriticalSection(&This->filter.csFilter); LeaveCriticalSection(&pin->thread_lock); return S_OK; } - This->rtStreamStart = tStart; - for (i = 1; i < (This->cStreams + 1); i++) { - hr = OutputPin_CommitAllocator((OutputPin *)This->ppPins[i]); + hr = BaseOutputPinImpl_Active((BaseOutputPin *)This->ppPins[i]); if (SUCCEEDED(hr)) hr_any = hr; } @@ -322,15 +333,15 @@ HRESULT WINAPI Parser_Run(IBaseFilter * iface, REFERENCE_TIME tStart) hr = hr_any; if (SUCCEEDED(hr)) { - LeaveCriticalSection(&This->csFilter); + LeaveCriticalSection(&This->filter.csFilter); hr = PullPin_StartProcessing(This->pInputPin); - EnterCriticalSection(&This->csFilter); + EnterCriticalSection(&This->filter.csFilter); } if (SUCCEEDED(hr)) - This->state = State_Running; + This->filter.state = State_Running; } - LeaveCriticalSection(&This->csFilter); + LeaveCriticalSection(&This->filter.csFilter); LeaveCriticalSection(&pin->thread_lock); return hr; @@ -338,18 +349,18 @@ HRESULT WINAPI Parser_Run(IBaseFilter * iface, REFERENCE_TIME tStart) HRESULT WINAPI Parser_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState) { - ParserImpl *This = (ParserImpl *)iface; - PullPin *pin = (PullPin *)This->ppPins[0]; + ParserImpl *This = impl_from_IBaseFilter(iface); + PullPin *pin = impl_PullPin_from_IPin(This->ppPins[0]); HRESULT hr = S_OK; TRACE("(%d, %p)\n", dwMilliSecsTimeout, pState); EnterCriticalSection(&pin->thread_lock); - EnterCriticalSection(&This->csFilter); + EnterCriticalSection(&This->filter.csFilter); { - *pState = This->state; + *pState = This->filter.state; } - LeaveCriticalSection(&This->csFilter); + LeaveCriticalSection(&This->filter.csFilter); if (This->pInputPin && (PullPin_WaitForStateChange(This->pInputPin, dwMilliSecsTimeout) == S_FALSE)) hr = VFW_S_STATE_INTERMEDIATE; @@ -360,21 +371,13 @@ HRESULT WINAPI Parser_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FI HRESULT WINAPI Parser_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock) { - ParserImpl *This = (ParserImpl *)iface; - PullPin *pin = (PullPin *)This->ppPins[0]; + ParserImpl *This = impl_from_IBaseFilter(iface); + PullPin *pin = impl_PullPin_from_IPin(This->ppPins[0]); TRACE("(%p)\n", pClock); EnterCriticalSection(&pin->thread_lock); - EnterCriticalSection(&This->csFilter); - { - if (This->pClock) - IReferenceClock_Release(This->pClock); - This->pClock = pClock; - if (This->pClock) - IReferenceClock_AddRef(This->pClock); - } - LeaveCriticalSection(&This->csFilter); + BaseFilterImpl_SetSyncSource(iface,pClock); LeaveCriticalSection(&pin->thread_lock); return S_OK; @@ -382,48 +385,14 @@ HRESULT WINAPI Parser_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock HRESULT WINAPI Parser_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock) { - ParserImpl *This = (ParserImpl *)iface; - - TRACE("(%p)\n", ppClock); - - EnterCriticalSection(&This->csFilter); - { - *ppClock = This->pClock; - if (This->pClock) - IReferenceClock_AddRef(This->pClock); - } - LeaveCriticalSection(&This->csFilter); - - return S_OK; + return BaseFilterImpl_GetSyncSource(iface, ppClock); } /** IBaseFilter implementation **/ -/* FIXME: WRONG */ -static HRESULT Parser_GetPin(IBaseFilter *iface, ULONG pos, IPin **pin, DWORD *lastsynctick) -{ - ParserImpl *This = (ParserImpl *)iface; - - *lastsynctick = This->lastpinchange; - - TRACE("Asking for pos %x\n", pos); - - /* Input pin also has a pin, hence the > and not >= */ - if (pos > This->cStreams) - return S_FALSE; - - *pin = This->ppPins[pos]; - IPin_AddRef(*pin); - return S_OK; -} - HRESULT WINAPI Parser_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum) { - ParserImpl *This = (ParserImpl *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum); - - return IEnumPinsImpl_Construct(ppEnum, Parser_GetPin, iface); + return BaseFilterImpl_EnumPins(iface,ppEnum); } HRESULT WINAPI Parser_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin) @@ -437,45 +406,32 @@ HRESULT WINAPI Parser_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin) HRESULT WINAPI Parser_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo) { - ParserImpl *This = (ParserImpl *)iface; - - TRACE("(%p)\n", pInfo); - - strcpyW(pInfo->achName, This->filterInfo.achName); - pInfo->pGraph = This->filterInfo.pGraph; - - if (pInfo->pGraph) - IFilterGraph_AddRef(pInfo->pGraph); - - return S_OK; + return BaseFilterImpl_QueryFilterInfo(iface, pInfo); } HRESULT WINAPI Parser_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName) { - HRESULT hr = S_OK; - ParserImpl *This = (ParserImpl *)iface; - - TRACE("(%p, %s)\n", pGraph, debugstr_w(pName)); - - EnterCriticalSection(&This->csFilter); - { - if (pName) - strcpyW(This->filterInfo.achName, pName); - else - *This->filterInfo.achName = '\0'; - This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */ - } - LeaveCriticalSection(&This->csFilter); - - return hr; + return BaseFilterImpl_JoinFilterGraph(iface, pGraph, pName); } HRESULT WINAPI Parser_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo) { - TRACE("(%p)\n", pVendorInfo); - return E_NOTIMPL; + return BaseFilterImpl_QueryVendorInfo(iface, pVendorInfo); } +static const BasePinFuncTable output_BaseFuncTable = { + NULL, + BaseOutputPinImpl_AttemptConnection, + BasePinImpl_GetMediaTypeVersion, + Parser_OutputPin_GetMediaType +}; + +static const BaseOutputPinFuncTable output_BaseOutputFuncTable = { + Parser_OutputPin_DecideBufferSize, + Parser_OutputPin_DecideAllocator, + Parser_OutputPin_BreakConnect +}; + HRESULT Parser_AddPin(ParserImpl * This, const PIN_INFO * piOutput, ALLOCATOR_PROPERTIES * props, const AM_MEDIA_TYPE * amt) { IPin ** ppOldPins; @@ -486,21 +442,20 @@ HRESULT Parser_AddPin(ParserImpl * This, const PIN_INFO * piOutput, ALLOCATOR_PR This->ppPins = CoTaskMemAlloc((This->cStreams + 2) * sizeof(IPin *)); memcpy(This->ppPins, ppOldPins, (This->cStreams + 1) * sizeof(IPin *)); - hr = OutputPin_Construct(&Parser_OutputPin_Vtbl, sizeof(Parser_OutputPin), piOutput, props, NULL, Parser_OutputPin_QueryAccept, &This->csFilter, This->ppPins + (This->cStreams + 1)); + hr = BaseOutputPin_Construct(&Parser_OutputPin_Vtbl, sizeof(Parser_OutputPin), piOutput, &output_BaseFuncTable, &output_BaseOutputFuncTable, &This->filter.csFilter, This->ppPins + (This->cStreams + 1)); if (SUCCEEDED(hr)) { IPin *pPin = This->ppPins[This->cStreams + 1]; - Parser_OutputPin *pin = (Parser_OutputPin *)pPin; + Parser_OutputPin *pin = unsafe_impl_Parser_OutputPin_from_IPin(pPin); pin->pmt = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE)); CopyMediaType(pin->pmt, amt); pin->dwSamplesProcessed = 0; - pin->pin.pin.pUserData = This->ppPins[This->cStreams + 1]; pin->pin.pin.pinInfo.pFilter = (LPVOID)This; - pin->pin.custom_allocator = 1; + pin->allocProps = *props; This->cStreams++; - This->lastpinchange = GetTickCount(); + BaseFilterImpl_IncrementPinVersion(&This->filter); CoTaskMemFree(ppOldPins); } else @@ -528,31 +483,31 @@ static HRESULT Parser_RemoveOutputPins(ParserImpl * This) for (i = 0; i < This->cStreams; i++) { - hr = OutputPin_DeliverDisconnect((OutputPin *)ppOldPins[i + 1]); + hr = ((BaseOutputPin *)ppOldPins[i + 1])->pFuncsTable->pfnBreakConnect((BaseOutputPin *)ppOldPins[i + 1]); TRACE("Disconnect: %08x\n", hr); IPin_Release(ppOldPins[i + 1]); } - This->lastpinchange = GetTickCount(); + BaseFilterImpl_IncrementPinVersion(&This->filter); This->cStreams = 0; CoTaskMemFree(ppOldPins); return S_OK; } -static HRESULT Parser_ChangeCurrent(IBaseFilter *iface) +static HRESULT WINAPI Parser_ChangeStart(IMediaSeeking *iface) { - FIXME("(%p) filter hasn't implemented current position change!\n", iface); + FIXME("(%p) filter hasn't implemented start position change!\n", iface); return S_OK; } -static HRESULT Parser_ChangeStop(IBaseFilter *iface) +static HRESULT WINAPI Parser_ChangeStop(IMediaSeeking *iface) { FIXME("(%p) filter hasn't implemented stop position change!\n", iface); return S_OK; } -static HRESULT Parser_ChangeRate(IBaseFilter *iface) +static HRESULT WINAPI Parser_ChangeRate(IMediaSeeking *iface) { FIXME("(%p) filter hasn't implemented rate change!\n", iface); return S_OK; @@ -585,28 +540,98 @@ static const IMediaSeekingVtbl Parser_Seeking_Vtbl = Parser_Seeking_QueryInterface, Parser_Seeking_AddRef, Parser_Seeking_Release, - MediaSeekingImpl_GetCapabilities, - MediaSeekingImpl_CheckCapabilities, - MediaSeekingImpl_IsFormatSupported, - MediaSeekingImpl_QueryPreferredFormat, - MediaSeekingImpl_GetTimeFormat, - MediaSeekingImpl_IsUsingTimeFormat, - MediaSeekingImpl_SetTimeFormat, - MediaSeekingImpl_GetDuration, - MediaSeekingImpl_GetStopPosition, - MediaSeekingImpl_GetCurrentPosition, - MediaSeekingImpl_ConvertTimeFormat, - MediaSeekingImpl_SetPositions, - MediaSeekingImpl_GetPositions, - MediaSeekingImpl_GetAvailable, - MediaSeekingImpl_SetRate, - MediaSeekingImpl_GetRate, - MediaSeekingImpl_GetPreroll + SourceSeekingImpl_GetCapabilities, + SourceSeekingImpl_CheckCapabilities, + SourceSeekingImpl_IsFormatSupported, + SourceSeekingImpl_QueryPreferredFormat, + SourceSeekingImpl_GetTimeFormat, + SourceSeekingImpl_IsUsingTimeFormat, + SourceSeekingImpl_SetTimeFormat, + SourceSeekingImpl_GetDuration, + SourceSeekingImpl_GetStopPosition, + SourceSeekingImpl_GetCurrentPosition, + SourceSeekingImpl_ConvertTimeFormat, + SourceSeekingImpl_SetPositions, + SourceSeekingImpl_GetPositions, + SourceSeekingImpl_GetAvailable, + SourceSeekingImpl_SetRate, + SourceSeekingImpl_GetRate, + SourceSeekingImpl_GetPreroll }; +static HRESULT WINAPI Parser_OutputPin_DecideBufferSize(BaseOutputPin *iface, IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest) +{ + Parser_OutputPin *This = (Parser_OutputPin*)iface; + ALLOCATOR_PROPERTIES actual; + + if (ppropInputRequest->cbAlign && ppropInputRequest->cbAlign != This->allocProps.cbAlign) + FIXME("Requested Buffer cbAlign mismatch %i,%i\n",This->allocProps.cbAlign, ppropInputRequest->cbAlign); + if (ppropInputRequest->cbPrefix) + FIXME("Requested Buffer cbPrefix mismatch %i,%i\n",This->allocProps.cbPrefix, ppropInputRequest->cbPrefix); + if (ppropInputRequest->cbBuffer) + FIXME("Requested Buffer cbBuffer mismatch %i,%i\n",This->allocProps.cbBuffer, ppropInputRequest->cbBuffer); + if (ppropInputRequest->cBuffers) + FIXME("Requested Buffer cBuffers mismatch %i,%i\n",This->allocProps.cBuffers, ppropInputRequest->cBuffers); + + return IMemAllocator_SetProperties(pAlloc, &This->allocProps, &actual); +} + +static HRESULT WINAPI Parser_OutputPin_GetMediaType(BasePin *iface, int iPosition, AM_MEDIA_TYPE *pmt) +{ + Parser_OutputPin *This = (Parser_OutputPin*)iface; + if (iPosition < 0) + return E_INVALIDARG; + if (iPosition > 0) + return VFW_S_NO_MORE_ITEMS; + CopyMediaType(pmt, This->pmt); + return S_OK; +} + +static HRESULT WINAPI Parser_OutputPin_DecideAllocator(BaseOutputPin *iface, IMemInputPin *pPin, IMemAllocator **pAlloc) +{ + Parser_OutputPin *This = (Parser_OutputPin*)iface; + HRESULT hr; + + *pAlloc = NULL; + + if (This->alloc) + { + hr = IMemInputPin_NotifyAllocator(pPin, This->alloc, This->readonly); + if (SUCCEEDED(hr)) + { + *pAlloc = This->alloc; + IMemAllocator_AddRef(*pAlloc); + } + } + else + hr = VFW_E_NO_ALLOCATOR; + + return hr; +} + +static HRESULT WINAPI Parser_OutputPin_BreakConnect(BaseOutputPin *This) +{ + HRESULT hr; + + TRACE("(%p)->()\n", This); + + EnterCriticalSection(This->pin.pCritSec); + if (!This->pin.pConnectedTo || !This->pMemInputPin) + hr = VFW_E_NOT_CONNECTED; + else + { + hr = IPin_Disconnect(This->pin.pConnectedTo); + IPin_Disconnect(&This->pin.IPin_iface); + } + LeaveCriticalSection(This->pin.pCritSec); + + return hr; +} + + static HRESULT WINAPI Parser_OutputPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv) { - Parser_OutputPin *This = (Parser_OutputPin *)iface; + Parser_OutputPin *This = unsafe_impl_Parser_OutputPin_from_IPin(iface); TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv); @@ -616,10 +641,9 @@ static HRESULT WINAPI Parser_OutputPin_QueryInterface(IPin * iface, REFIID riid, *ppv = iface; else if (IsEqualIID(riid, &IID_IPin)) *ppv = iface; + /* The Parser filter does not support querying IMediaSeeking, return it directly */ else if (IsEqualIID(riid, &IID_IMediaSeeking)) - { - return IBaseFilter_QueryInterface(This->pin.pin.pinInfo.pFilter, &IID_IMediaSeeking, ppv); - } + *ppv = &impl_from_IBaseFilter(This->pin.pin.pinInfo.pFilter)->sourceSeeking; if (*ppv) { @@ -634,7 +658,7 @@ static HRESULT WINAPI Parser_OutputPin_QueryInterface(IPin * iface, REFIID riid, static ULONG WINAPI Parser_OutputPin_Release(IPin * iface) { - Parser_OutputPin *This = (Parser_OutputPin *)iface; + Parser_OutputPin *This = unsafe_impl_Parser_OutputPin_from_IPin(iface); ULONG refCount = InterlockedDecrement(&This->pin.pin.refCount); TRACE("(%p)->() Release from %d\n", iface, refCount + 1); @@ -644,42 +668,30 @@ static ULONG WINAPI Parser_OutputPin_Release(IPin * iface) FreeMediaType(This->pmt); CoTaskMemFree(This->pmt); FreeMediaType(&This->pin.pin.mtCurrent); + if (This->pin.pAllocator) + IMemAllocator_Release(This->pin.pAllocator); CoTaskMemFree(This); return 0; } return refCount; } -static HRESULT WINAPI Parser_OutputPin_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum) -{ - ENUMMEDIADETAILS emd; - Parser_OutputPin *This = (Parser_OutputPin *)iface; - - TRACE("(%p)\n", ppEnum); - - /* override this method to allow enumeration of your types */ - emd.cMediaTypes = 1; - emd.pMediaTypes = This->pmt; - - return IEnumMediaTypesImpl_Construct(&emd, ppEnum); -} - static HRESULT WINAPI Parser_OutputPin_Connect(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) { - Parser_OutputPin *This = (Parser_OutputPin *)iface; - ParserImpl *parser = (ParserImpl *)This->pin.pin.pinInfo.pFilter; + Parser_OutputPin *This = unsafe_impl_Parser_OutputPin_from_IPin(iface); + ParserImpl *parser = impl_from_IBaseFilter(This->pin.pin.pinInfo.pFilter); /* Set the allocator to our input pin's */ EnterCriticalSection(This->pin.pin.pCritSec); - This->pin.alloc = parser->pInputPin->pAlloc; + This->alloc = parser->pInputPin->pAlloc; LeaveCriticalSection(This->pin.pin.pCritSec); - return OutputPin_Connect(iface, pReceivePin, pmt); + return BaseOutputPinImpl_Connect(iface, pReceivePin, pmt); } -static HRESULT Parser_OutputPin_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt) +static HRESULT WINAPI Parser_OutputPin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE * pmt) { - Parser_OutputPin *This = iface; + Parser_OutputPin *This = unsafe_impl_Parser_OutputPin_from_IPin(iface); TRACE("()\n"); dump_AM_MEDIA_TYPE(pmt); @@ -690,29 +702,54 @@ static HRESULT Parser_OutputPin_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * static const IPinVtbl Parser_OutputPin_Vtbl = { Parser_OutputPin_QueryInterface, - IPinImpl_AddRef, + BasePinImpl_AddRef, Parser_OutputPin_Release, Parser_OutputPin_Connect, - OutputPin_ReceiveConnection, - OutputPin_Disconnect, - IPinImpl_ConnectedTo, - IPinImpl_ConnectionMediaType, - IPinImpl_QueryPinInfo, - IPinImpl_QueryDirection, - IPinImpl_QueryId, - IPinImpl_QueryAccept, - Parser_OutputPin_EnumMediaTypes, - IPinImpl_QueryInternalConnections, - OutputPin_EndOfStream, - OutputPin_BeginFlush, - OutputPin_EndFlush, - OutputPin_NewSegment + BaseOutputPinImpl_ReceiveConnection, + BaseOutputPinImpl_Disconnect, + BasePinImpl_ConnectedTo, + BasePinImpl_ConnectionMediaType, + BasePinImpl_QueryPinInfo, + BasePinImpl_QueryDirection, + BasePinImpl_QueryId, + Parser_OutputPin_QueryAccept, + BasePinImpl_EnumMediaTypes, + BasePinImpl_QueryInternalConnections, + BaseOutputPinImpl_EndOfStream, + BaseOutputPinImpl_BeginFlush, + BaseOutputPinImpl_EndFlush, + BasePinImpl_NewSegment }; +static HRESULT WINAPI Parser_PullPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv) +{ + PullPin *This = impl_PullPin_from_IPin(iface); + + TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv); + + *ppv = NULL; + + /* + * It is important to capture the request for the IMediaSeeking interface before it is passed + * on to PullPin_QueryInterface, this is necessary since the Parser filter does not support + * querying IMediaSeeking + */ + if (IsEqualIID(riid, &IID_IMediaSeeking)) + *ppv = &impl_from_IBaseFilter(This->pin.pinInfo.pFilter)->sourceSeeking; + + if (*ppv) + { + IUnknown_AddRef((IUnknown *)(*ppv)); + return S_OK; + } + + return PullPin_QueryInterface(iface, riid, ppv); +} + static HRESULT WINAPI Parser_PullPin_Disconnect(IPin * iface) { HRESULT hr; - PullPin *This = (PullPin *)iface; + PullPin *This = impl_PullPin_from_IPin(iface); TRACE("()\n"); @@ -722,7 +759,7 @@ static HRESULT WINAPI Parser_PullPin_Disconnect(IPin * iface) if (This->pin.pConnectedTo) { FILTER_STATE state; - ParserImpl *Parser = (ParserImpl *)This->pin.pinInfo.pFilter; + ParserImpl *Parser = impl_from_IBaseFilter(This->pin.pinInfo.pFilter); LeaveCriticalSection(This->pin.pCritSec); hr = IBaseFilter_GetState(This->pin.pinInfo.pFilter, INFINITE, &state); @@ -733,7 +770,7 @@ static HRESULT WINAPI Parser_PullPin_Disconnect(IPin * iface) LeaveCriticalSection(This->pin.pCritSec); PullPin_Disconnect(iface); EnterCriticalSection(This->pin.pCritSec); - hr = Parser_RemoveOutputPins((ParserImpl *)This->pin.pinInfo.pFilter); + hr = Parser_RemoveOutputPins(impl_from_IBaseFilter(This->pin.pinInfo.pFilter)); } else hr = VFW_E_NOT_STOPPED; @@ -756,32 +793,41 @@ static HRESULT WINAPI Parser_PullPin_ReceiveConnection(IPin * iface, IPin * pRec hr = PullPin_ReceiveConnection(iface, pReceivePin, pmt); if (FAILED(hr)) { - IPinImpl *This = (IPinImpl *)iface; + BasePin *This = (BasePin *)iface; EnterCriticalSection(This->pCritSec); - Parser_RemoveOutputPins((ParserImpl *)This->pinInfo.pFilter); + Parser_RemoveOutputPins(impl_from_IBaseFilter(This->pinInfo.pFilter)); LeaveCriticalSection(This->pCritSec); } return hr; } +static HRESULT WINAPI Parser_PullPin_EnumMediaTypes(IPin *iface, IEnumMediaTypes **ppEnum) +{ + BasePin *This = (BasePin *)iface; + + TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum); + + return EnumMediaTypes_Construct(This, BasePinImpl_GetMediaType, BasePinImpl_GetMediaTypeVersion, ppEnum); +} + static const IPinVtbl Parser_InputPin_Vtbl = { - PullPin_QueryInterface, - IPinImpl_AddRef, + Parser_PullPin_QueryInterface, + BasePinImpl_AddRef, PullPin_Release, - InputPin_Connect, + BaseInputPinImpl_Connect, Parser_PullPin_ReceiveConnection, Parser_PullPin_Disconnect, - IPinImpl_ConnectedTo, - IPinImpl_ConnectionMediaType, - IPinImpl_QueryPinInfo, - IPinImpl_QueryDirection, - IPinImpl_QueryId, - IPinImpl_QueryAccept, - IPinImpl_EnumMediaTypes, - IPinImpl_QueryInternalConnections, + BasePinImpl_ConnectedTo, + BasePinImpl_ConnectionMediaType, + BasePinImpl_QueryPinInfo, + BasePinImpl_QueryDirection, + BasePinImpl_QueryId, + PullPin_QueryAccept, + Parser_PullPin_EnumMediaTypes, + BasePinImpl_QueryInternalConnections, PullPin_EndOfStream, PullPin_BeginFlush, PullPin_EndFlush, diff --git a/reactos/dll/directx/quartz/parser.h b/reactos/dll/directx/quartz/parser.h index b5423885400..996415a40df 100644 --- a/reactos/dll/directx/quartz/parser.h +++ b/reactos/dll/directx/quartz/parser.h @@ -28,37 +28,33 @@ typedef HRESULT (*PFN_DISCONNECT) (LPVOID iface); struct ParserImpl { - const IBaseFilterVtbl *lpVtbl; + BaseFilter filter; - LONG refCount; - CRITICAL_SECTION csFilter; - FILTER_STATE state; - REFERENCE_TIME rtStreamStart; - IReferenceClock * pClock; PFN_CLEANUP fnCleanup; PFN_DISCONNECT fnDisconnect; - FILTER_INFO filterInfo; - CLSID clsid; PullPin * pInputPin; IPin ** ppPins; ULONG cStreams; - DWORD lastpinchange; - MediaSeekingImpl mediaSeeking; + SourceSeeking sourceSeeking; }; typedef struct Parser_OutputPin { - OutputPin pin; + BaseOutputPin pin; AM_MEDIA_TYPE * pmt; LONGLONG dwSamplesProcessed; + ALLOCATOR_PROPERTIES allocProps; + + IMemAllocator *alloc; + BOOL readonly; } Parser_OutputPin; extern HRESULT Parser_AddPin(ParserImpl * This, const PIN_INFO * piOutput, ALLOCATOR_PROPERTIES * props, const AM_MEDIA_TYPE * amt); extern HRESULT Parser_Create(ParserImpl*, const IBaseFilterVtbl *, const CLSID*, PFN_PROCESS_SAMPLE, PFN_QUERY_ACCEPT, PFN_PRE_CONNECT, - PFN_CLEANUP, PFN_DISCONNECT, REQUESTPROC, STOPPROCESSPROC, CHANGEPROC stop, CHANGEPROC current, CHANGEPROC rate); + PFN_CLEANUP, PFN_DISCONNECT, REQUESTPROC, STOPPROCESSPROC, SourceSeeking_ChangeStop stop, SourceSeeking_ChangeStart start, SourceSeeking_ChangeRate rate); /* Override the _Release function and call this when releasing */ extern void Parser_Destroy(ParserImpl *This); @@ -78,3 +74,9 @@ extern HRESULT WINAPI Parser_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppP extern HRESULT WINAPI Parser_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo); extern HRESULT WINAPI Parser_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName); extern HRESULT WINAPI Parser_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo); + +/* COM helpers */ +static inline Parser_OutputPin *unsafe_impl_Parser_OutputPin_from_IPin( IPin *iface ) +{ + return CONTAINING_RECORD(iface, Parser_OutputPin, pin.pin.IPin_iface); +} diff --git a/reactos/dll/directx/quartz/pin.c b/reactos/dll/directx/quartz/pin.c index 20d7aedde9b..0d8edb0a491 100644 --- a/reactos/dll/directx/quartz/pin.c +++ b/reactos/dll/directx/quartz/pin.c @@ -29,9 +29,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(quartz); -static const IPinVtbl InputPin_Vtbl; -static const IPinVtbl OutputPin_Vtbl; -static const IMemInputPinVtbl MemInputPin_Vtbl; static const IPinVtbl PullPin_Vtbl; #define ALIGNDOWN(value,boundary) ((value)/(boundary)*(boundary)) @@ -45,7 +42,7 @@ typedef HRESULT (*SendPinFunc)( IPin *to, LPVOID arg ); * Return the first received error code (E_NOTIMPL is ignored) * If no errors occur: return the first received non-error-code that isn't S_OK */ -HRESULT updatehres( HRESULT original, HRESULT new ) +static HRESULT updatehres( HRESULT original, HRESULT new ) { if (FAILED( original ) || new == E_NOTIMPL) return original; @@ -137,6 +134,8 @@ static HRESULT SendFurther( IPin *from, SendPinFunc fnMiddle, LPVOID arg, SendPi } out: + if (enumpins) + IEnumPins_Release( enumpins ); if (pin_info.pFilter) IBaseFilter_Release( pin_info.pFilter ); return hr; @@ -154,333 +153,21 @@ static void Copy_PinInfo(PIN_INFO * pDest, const PIN_INFO * pSrc) pDest->pFilter = pSrc->pFilter; } -/*** Common pin functions ***/ - -ULONG WINAPI IPinImpl_AddRef(IPin * iface) -{ - IPinImpl *This = (IPinImpl *)iface; - ULONG refCount = InterlockedIncrement(&This->refCount); - - TRACE("(%p)->() AddRef from %d\n", iface, refCount - 1); - - return refCount; -} - -HRESULT WINAPI IPinImpl_Disconnect(IPin * iface) -{ - HRESULT hr; - IPinImpl *This = (IPinImpl *)iface; - - TRACE("()\n"); - - EnterCriticalSection(This->pCritSec); - { - if (This->pConnectedTo) - { - IPin_Release(This->pConnectedTo); - This->pConnectedTo = NULL; - FreeMediaType(&This->mtCurrent); - ZeroMemory(&This->mtCurrent, sizeof(This->mtCurrent)); - hr = S_OK; - } - else - hr = S_FALSE; - } - LeaveCriticalSection(This->pCritSec); - - return hr; -} - -HRESULT WINAPI IPinImpl_ConnectedTo(IPin * iface, IPin ** ppPin) -{ - HRESULT hr; - IPinImpl *This = (IPinImpl *)iface; - - TRACE("(%p)\n", ppPin); - - EnterCriticalSection(This->pCritSec); - { - if (This->pConnectedTo) - { - *ppPin = This->pConnectedTo; - IPin_AddRef(*ppPin); - hr = S_OK; - } - else - { - hr = VFW_E_NOT_CONNECTED; - *ppPin = NULL; - } - } - LeaveCriticalSection(This->pCritSec); - - return hr; -} - -HRESULT WINAPI IPinImpl_ConnectionMediaType(IPin * iface, AM_MEDIA_TYPE * pmt) -{ - HRESULT hr; - IPinImpl *This = (IPinImpl *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, pmt); - - EnterCriticalSection(This->pCritSec); - { - if (This->pConnectedTo) - { - CopyMediaType(pmt, &This->mtCurrent); - hr = S_OK; - } - else - { - ZeroMemory(pmt, sizeof(*pmt)); - hr = VFW_E_NOT_CONNECTED; - } - } - LeaveCriticalSection(This->pCritSec); - - return hr; -} - -HRESULT WINAPI IPinImpl_QueryPinInfo(IPin * iface, PIN_INFO * pInfo) -{ - IPinImpl *This = (IPinImpl *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, pInfo); - - Copy_PinInfo(pInfo, &This->pinInfo); - IBaseFilter_AddRef(pInfo->pFilter); - - return S_OK; -} - -HRESULT WINAPI IPinImpl_QueryDirection(IPin * iface, PIN_DIRECTION * pPinDir) -{ - IPinImpl *This = (IPinImpl *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, pPinDir); - - *pPinDir = This->pinInfo.dir; - - return S_OK; -} - -HRESULT WINAPI IPinImpl_QueryId(IPin * iface, LPWSTR * Id) -{ - IPinImpl *This = (IPinImpl *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, Id); - - *Id = CoTaskMemAlloc((strlenW(This->pinInfo.achName) + 1) * sizeof(WCHAR)); - if (!*Id) - return E_OUTOFMEMORY; - - strcpyW(*Id, This->pinInfo.achName); - - return S_OK; -} - -HRESULT WINAPI IPinImpl_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt) -{ - IPinImpl *This = (IPinImpl *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, pmt); - - return (This->fnQueryAccept(This->pUserData, pmt) == S_OK ? S_OK : S_FALSE); -} - -HRESULT WINAPI IPinImpl_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum) -{ - IPinImpl *This = (IPinImpl *)iface; - ENUMMEDIADETAILS emd; - - TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum); - - /* override this method to allow enumeration of your types */ - emd.cMediaTypes = 0; - emd.pMediaTypes = NULL; - - return IEnumMediaTypesImpl_Construct(&emd, ppEnum); -} - -HRESULT WINAPI IPinImpl_QueryInternalConnections(IPin * iface, IPin ** apPin, ULONG * cPin) -{ - IPinImpl *This = (IPinImpl *)iface; - - TRACE("(%p/%p)->(%p, %p)\n", This, iface, apPin, cPin); - - return E_NOTIMPL; /* to tell caller that all input pins connected to all output pins */ -} - -/*** IPin implementation for an input pin ***/ - -HRESULT WINAPI InputPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv) -{ - InputPin *This = (InputPin *)iface; - - TRACE("(%p)->(%s, %p)\n", iface, qzdebugstr_guid(riid), ppv); - - *ppv = NULL; - - if (IsEqualIID(riid, &IID_IUnknown)) - *ppv = iface; - else if (IsEqualIID(riid, &IID_IPin)) - *ppv = iface; - else if (IsEqualIID(riid, &IID_IMemInputPin)) - *ppv = &This->lpVtblMemInput; - else if (IsEqualIID(riid, &IID_IMediaSeeking)) - { - return IBaseFilter_QueryInterface(This->pin.pinInfo.pFilter, &IID_IMediaSeeking, ppv); - } - - if (*ppv) - { - IUnknown_AddRef((IUnknown *)(*ppv)); - return S_OK; - } - - FIXME("No interface for %s!\n", qzdebugstr_guid(riid)); - - return E_NOINTERFACE; -} - -ULONG WINAPI InputPin_Release(IPin * iface) -{ - InputPin *This = (InputPin *)iface; - ULONG refCount = InterlockedDecrement(&This->pin.refCount); - - TRACE("(%p)->() Release from %d\n", iface, refCount + 1); - - if (!refCount) - { - FreeMediaType(&This->pin.mtCurrent); - if (This->pAllocator) - IMemAllocator_Release(This->pAllocator); - This->pAllocator = NULL; - This->pin.lpVtbl = NULL; - CoTaskMemFree(This); - return 0; - } - else - return refCount; -} - -HRESULT WINAPI InputPin_Connect(IPin * iface, IPin * pConnector, const AM_MEDIA_TYPE * pmt) -{ - ERR("Outgoing connection on an input pin! (%p, %p)\n", pConnector, pmt); - - return E_UNEXPECTED; -} - - -HRESULT WINAPI InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) -{ - InputPin *This = (InputPin *)iface; - PIN_DIRECTION pindirReceive; - HRESULT hr = S_OK; - - TRACE("(%p, %p)\n", pReceivePin, pmt); - dump_AM_MEDIA_TYPE(pmt); - - EnterCriticalSection(This->pin.pCritSec); - { - if (This->pin.pConnectedTo) - hr = VFW_E_ALREADY_CONNECTED; - - if (SUCCEEDED(hr) && This->pin.fnQueryAccept(This->pin.pUserData, pmt) != S_OK) - hr = VFW_E_TYPE_NOT_ACCEPTED; /* FIXME: shouldn't we just map common errors onto - * VFW_E_TYPE_NOT_ACCEPTED and pass the value on otherwise? */ - - 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)) - { - CopyMediaType(&This->pin.mtCurrent, pmt); - This->pin.pConnectedTo = pReceivePin; - IPin_AddRef(pReceivePin); - } - } - LeaveCriticalSection(This->pin.pCritSec); - - return hr; -} - static HRESULT deliver_endofstream(IPin* pin, LPVOID unused) { return IPin_EndOfStream( pin ); } -HRESULT WINAPI InputPin_EndOfStream(IPin * iface) -{ - HRESULT hr = S_OK; - InputPin *This = (InputPin *)iface; - - TRACE("(%p)\n", This); - - EnterCriticalSection(This->pin.pCritSec); - if (This->flushing) - hr = S_FALSE; - else - This->end_of_stream = 1; - LeaveCriticalSection(This->pin.pCritSec); - - if (hr == S_OK) - hr = SendFurther( iface, deliver_endofstream, NULL, NULL ); - return hr; -} - static HRESULT deliver_beginflush(IPin* pin, LPVOID unused) { return IPin_BeginFlush( pin ); } -HRESULT WINAPI InputPin_BeginFlush(IPin * iface) -{ - InputPin *This = (InputPin *)iface; - HRESULT hr; - TRACE("() semi-stub\n"); - - EnterCriticalSection(This->pin.pCritSec); - This->flushing = 1; - - if (This->fnCleanProc) - This->fnCleanProc(This->pin.pUserData); - - hr = SendFurther( iface, deliver_beginflush, NULL, NULL ); - LeaveCriticalSection(This->pin.pCritSec); - - return hr; -} - static HRESULT deliver_endflush(IPin* pin, LPVOID unused) { return IPin_EndFlush( pin ); } -HRESULT WINAPI InputPin_EndFlush(IPin * iface) -{ - InputPin *This = (InputPin *)iface; - HRESULT hr; - TRACE("(%p)\n", This); - - EnterCriticalSection(This->pin.pCritSec); - This->flushing = This->end_of_stream = 0; - - hr = SendFurther( iface, deliver_endflush, NULL, NULL ); - LeaveCriticalSection(This->pin.pCritSec); - - return hr; -} - typedef struct newsegmentargs { REFERENCE_TIME tStart, tStop; @@ -493,578 +180,28 @@ static HRESULT deliver_newsegment(IPin *pin, LPVOID data) return IPin_NewSegment(pin, args->tStart, args->tStop, args->rate); } -HRESULT WINAPI InputPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) -{ - InputPin *This = (InputPin *)iface; - newsegmentargs args; - - TRACE("(%x%08x, %x%08x, %e)\n", (ULONG)(tStart >> 32), (ULONG)tStart, (ULONG)(tStop >> 32), (ULONG)tStop, dRate); - - args.tStart = This->tStart = tStart; - args.tStop = This->tStop = tStop; - args.rate = This->dRate = dRate; - - return SendFurther( iface, deliver_newsegment, &args, NULL ); -} - -static const IPinVtbl InputPin_Vtbl = -{ - InputPin_QueryInterface, - IPinImpl_AddRef, - InputPin_Release, - InputPin_Connect, - InputPin_ReceiveConnection, - IPinImpl_Disconnect, - IPinImpl_ConnectedTo, - IPinImpl_ConnectionMediaType, - IPinImpl_QueryPinInfo, - IPinImpl_QueryDirection, - IPinImpl_QueryId, - IPinImpl_QueryAccept, - IPinImpl_EnumMediaTypes, - IPinImpl_QueryInternalConnections, - InputPin_EndOfStream, - InputPin_BeginFlush, - InputPin_EndFlush, - InputPin_NewSegment -}; - -/*** IMemInputPin implementation ***/ - -static inline InputPin *impl_from_IMemInputPin( IMemInputPin *iface ) -{ - return (InputPin *)((char*)iface - FIELD_OFFSET(InputPin, lpVtblMemInput)); -} - -static HRESULT WINAPI MemInputPin_QueryInterface(IMemInputPin * iface, REFIID riid, LPVOID * ppv) -{ - InputPin *This = impl_from_IMemInputPin(iface); - - return IPin_QueryInterface((IPin *)&This->pin, riid, ppv); -} - -static ULONG WINAPI MemInputPin_AddRef(IMemInputPin * iface) -{ - InputPin *This = impl_from_IMemInputPin(iface); - - return IPin_AddRef((IPin *)&This->pin); -} - -static ULONG WINAPI MemInputPin_Release(IMemInputPin * iface) -{ - InputPin *This = impl_from_IMemInputPin(iface); - - return IPin_Release((IPin *)&This->pin); -} - -static HRESULT WINAPI MemInputPin_GetAllocator(IMemInputPin * iface, IMemAllocator ** ppAllocator) -{ - InputPin *This = impl_from_IMemInputPin(iface); - - TRACE("(%p/%p)->(%p)\n", This, iface, ppAllocator); - - *ppAllocator = This->pAllocator; - if (*ppAllocator) - IMemAllocator_AddRef(*ppAllocator); - - return *ppAllocator ? S_OK : VFW_E_NO_ALLOCATOR; -} - -static HRESULT WINAPI MemInputPin_NotifyAllocator(IMemInputPin * iface, IMemAllocator * pAllocator, BOOL bReadOnly) -{ - InputPin *This = impl_from_IMemInputPin(iface); - - TRACE("(%p/%p)->(%p, %d)\n", This, iface, pAllocator, bReadOnly); - - if (bReadOnly) - FIXME("Read only flag not handled yet!\n"); - - /* FIXME: Should we release the allocator on disconnection? */ - if (!pAllocator) - { - WARN("Null allocator\n"); - return E_POINTER; - } - - if (This->preferred_allocator && pAllocator != This->preferred_allocator) - return E_FAIL; - - if (This->pAllocator) - IMemAllocator_Release(This->pAllocator); - This->pAllocator = pAllocator; - if (This->pAllocator) - IMemAllocator_AddRef(This->pAllocator); - - return S_OK; -} - -static HRESULT WINAPI MemInputPin_GetAllocatorRequirements(IMemInputPin * iface, ALLOCATOR_PROPERTIES * pProps) -{ - InputPin *This = impl_from_IMemInputPin(iface); - - TRACE("(%p/%p)->(%p)\n", This, iface, pProps); - - /* override this method if you have any specific requirements */ - - return E_NOTIMPL; -} - -static HRESULT WINAPI MemInputPin_Receive(IMemInputPin * iface, IMediaSample * pSample) -{ - InputPin *This = impl_from_IMemInputPin(iface); - HRESULT hr; - - /* this trace commented out for performance reasons */ - /*TRACE("(%p/%p)->(%p)\n", This, iface, pSample);*/ - hr = This->fnSampleProc(This->pin.pUserData, pSample); - return hr; -} - -static HRESULT WINAPI MemInputPin_ReceiveMultiple(IMemInputPin * iface, IMediaSample ** pSamples, LONG nSamples, LONG *nSamplesProcessed) -{ - HRESULT hr = S_OK; - InputPin *This = impl_from_IMemInputPin(iface); - - TRACE("(%p/%p)->(%p, %d, %p)\n", This, iface, pSamples, nSamples, nSamplesProcessed); - - for (*nSamplesProcessed = 0; *nSamplesProcessed < nSamples; (*nSamplesProcessed)++) - { - hr = IMemInputPin_Receive(iface, pSamples[*nSamplesProcessed]); - if (hr != S_OK) - break; - } - - return hr; -} - -static HRESULT WINAPI MemInputPin_ReceiveCanBlock(IMemInputPin * iface) -{ - InputPin *This = impl_from_IMemInputPin(iface); - - TRACE("(%p/%p)->()\n", This, iface); - - return S_OK; -} - -static const IMemInputPinVtbl MemInputPin_Vtbl = -{ - MemInputPin_QueryInterface, - MemInputPin_AddRef, - MemInputPin_Release, - MemInputPin_GetAllocator, - MemInputPin_NotifyAllocator, - MemInputPin_GetAllocatorRequirements, - MemInputPin_Receive, - MemInputPin_ReceiveMultiple, - MemInputPin_ReceiveCanBlock -}; - -/*** OutputPin implementation ***/ - -HRESULT WINAPI OutputPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv) -{ - OutputPin *This = (OutputPin *)iface; - - TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv); - - *ppv = NULL; - - if (IsEqualIID(riid, &IID_IUnknown)) - *ppv = iface; - else if (IsEqualIID(riid, &IID_IPin)) - *ppv = iface; - else if (IsEqualIID(riid, &IID_IMediaSeeking)) - { - return IBaseFilter_QueryInterface(This->pin.pinInfo.pFilter, &IID_IMediaSeeking, ppv); - } - - if (*ppv) - { - IUnknown_AddRef((IUnknown *)(*ppv)); - return S_OK; - } - - FIXME("No interface for %s!\n", qzdebugstr_guid(riid)); - - return E_NOINTERFACE; -} - -ULONG WINAPI OutputPin_Release(IPin * iface) -{ - OutputPin *This = (OutputPin *)iface; - ULONG refCount = InterlockedDecrement(&This->pin.refCount); - - TRACE("(%p)->() Release from %d\n", iface, refCount + 1); - - if (!refCount) - { - FreeMediaType(&This->pin.mtCurrent); - CoTaskMemFree(This); - return 0; - } - return refCount; -} - -HRESULT WINAPI OutputPin_Connect(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) -{ - HRESULT hr; - OutputPin *This = (OutputPin *)iface; - - TRACE("(%p/%p)->(%p, %p)\n", This, iface, pReceivePin, pmt); - dump_AM_MEDIA_TYPE(pmt); - - /* If we try to connect to ourself, we will definitely deadlock. - * There are other cases where we could deadlock too, but this - * catches the obvious case */ - assert(pReceivePin != iface); - - EnterCriticalSection(This->pin.pCritSec); - { - /* if we have been a specific type to connect with, then we can either connect - * with that or fail. We cannot choose different AM_MEDIA_TYPE */ - if (pmt && !IsEqualGUID(&pmt->majortype, &GUID_NULL) && !IsEqualGUID(&pmt->subtype, &GUID_NULL)) - hr = This->pConnectSpecific(iface, pReceivePin, pmt); - else - { - /* negotiate media type */ - - IEnumMediaTypes * pEnumCandidates; - AM_MEDIA_TYPE * pmtCandidate = NULL; /* Candidate media type */ - - if (SUCCEEDED(hr = IPin_EnumMediaTypes(iface, &pEnumCandidates))) - { - hr = VFW_E_NO_ACCEPTABLE_TYPES; /* Assume the worst, but set to S_OK if connected successfully */ - - /* try this filter's media types first */ - while (S_OK == IEnumMediaTypes_Next(pEnumCandidates, 1, &pmtCandidate, NULL)) - { - assert(pmtCandidate); - dump_AM_MEDIA_TYPE(pmtCandidate); - if (!IsEqualGUID(&FORMAT_None, &pmtCandidate->formattype) - && !IsEqualGUID(&GUID_NULL, &pmtCandidate->formattype)) - assert(pmtCandidate->pbFormat); - if (( !pmt || CompareMediaTypes(pmt, pmtCandidate, TRUE) ) && - (This->pConnectSpecific(iface, pReceivePin, pmtCandidate) == S_OK)) - { - hr = S_OK; - DeleteMediaType(pmtCandidate); - break; - } - DeleteMediaType(pmtCandidate); - pmtCandidate = NULL; - } - IEnumMediaTypes_Release(pEnumCandidates); - } - - /* then try receiver filter's media types */ - if (hr != S_OK && SUCCEEDED(hr = IPin_EnumMediaTypes(pReceivePin, &pEnumCandidates))) /* if we haven't already connected successfully */ - { - hr = VFW_E_NO_ACCEPTABLE_TYPES; /* Assume the worst, but set to S_OK if connected successfully */ - - while (S_OK == IEnumMediaTypes_Next(pEnumCandidates, 1, &pmtCandidate, NULL)) - { - assert(pmtCandidate); - dump_AM_MEDIA_TYPE(pmtCandidate); - if (( !pmt || CompareMediaTypes(pmt, pmtCandidate, TRUE) ) && - (This->pConnectSpecific(iface, pReceivePin, pmtCandidate) == S_OK)) - { - hr = S_OK; - DeleteMediaType(pmtCandidate); - break; - } - DeleteMediaType(pmtCandidate); - pmtCandidate = NULL; - } /* while */ - IEnumMediaTypes_Release(pEnumCandidates); - } /* if not found */ - } /* if negotiate media type */ - } /* if succeeded */ - LeaveCriticalSection(This->pin.pCritSec); - - TRACE(" -- %x\n", hr); - return hr; -} - -HRESULT WINAPI OutputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) -{ - ERR("Incoming connection on an output pin! (%p, %p)\n", pReceivePin, pmt); - - return E_UNEXPECTED; -} - -HRESULT WINAPI OutputPin_Disconnect(IPin * iface) -{ - HRESULT hr; - OutputPin *This = (OutputPin *)iface; - - TRACE("()\n"); - - EnterCriticalSection(This->pin.pCritSec); - { - if (This->pMemInputPin) - { - IMemInputPin_Release(This->pMemInputPin); - This->pMemInputPin = NULL; - } - if (This->pin.pConnectedTo) - { - IPin_Release(This->pin.pConnectedTo); - This->pin.pConnectedTo = NULL; - FreeMediaType(&This->pin.mtCurrent); - ZeroMemory(&This->pin.mtCurrent, sizeof(This->pin.mtCurrent)); - hr = S_OK; - } - else - hr = S_FALSE; - } - LeaveCriticalSection(This->pin.pCritSec); - - return hr; -} - -HRESULT WINAPI OutputPin_EndOfStream(IPin * iface) -{ - TRACE("()\n"); - - /* not supposed to do anything in an output pin */ - - return E_UNEXPECTED; -} - -HRESULT WINAPI OutputPin_BeginFlush(IPin * iface) -{ - TRACE("(%p)->()\n", iface); - - /* not supposed to do anything in an output pin */ - - return E_UNEXPECTED; -} - -HRESULT WINAPI OutputPin_EndFlush(IPin * iface) -{ - TRACE("(%p)->()\n", iface); - - /* not supposed to do anything in an output pin */ - - return E_UNEXPECTED; -} - -HRESULT WINAPI OutputPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) -{ - TRACE("(%p)->(%x%08x, %x%08x, %e)\n", iface, (ULONG)(tStart >> 32), (ULONG)tStart, (ULONG)(tStop >> 32), (ULONG)tStop, dRate); - - /* not supposed to do anything in an output pin */ - - return E_UNEXPECTED; -} - -static const IPinVtbl OutputPin_Vtbl = -{ - OutputPin_QueryInterface, - IPinImpl_AddRef, - OutputPin_Release, - OutputPin_Connect, - OutputPin_ReceiveConnection, - OutputPin_Disconnect, - IPinImpl_ConnectedTo, - IPinImpl_ConnectionMediaType, - IPinImpl_QueryPinInfo, - IPinImpl_QueryDirection, - IPinImpl_QueryId, - IPinImpl_QueryAccept, - IPinImpl_EnumMediaTypes, - IPinImpl_QueryInternalConnections, - OutputPin_EndOfStream, - OutputPin_BeginFlush, - OutputPin_EndFlush, - OutputPin_NewSegment -}; - -HRESULT OutputPin_GetDeliveryBuffer(OutputPin * This, IMediaSample ** ppSample, REFERENCE_TIME * tStart, REFERENCE_TIME * tStop, DWORD dwFlags) -{ - HRESULT hr; - - TRACE("(%p, %p, %p, %x)\n", ppSample, tStart, tStop, dwFlags); - - EnterCriticalSection(This->pin.pCritSec); - { - if (!This->pin.pConnectedTo) - hr = VFW_E_NOT_CONNECTED; - else - { - IMemAllocator * pAlloc = NULL; - - hr = IMemInputPin_GetAllocator(This->pMemInputPin, &pAlloc); - - if (SUCCEEDED(hr)) - hr = IMemAllocator_GetBuffer(pAlloc, ppSample, tStart, tStop, dwFlags); - - if (SUCCEEDED(hr)) - hr = IMediaSample_SetTime(*ppSample, tStart, tStop); - - if (pAlloc) - IMemAllocator_Release(pAlloc); - } - } - LeaveCriticalSection(This->pin.pCritSec); - - return hr; -} - -HRESULT OutputPin_SendSample(OutputPin * This, IMediaSample * pSample) -{ - HRESULT hr = S_OK; - IMemInputPin * pMemConnected = NULL; - PIN_INFO pinInfo; - - EnterCriticalSection(This->pin.pCritSec); - { - if (!This->pin.pConnectedTo || !This->pMemInputPin) - hr = VFW_E_NOT_CONNECTED; - else - { - /* we don't have the lock held when using This->pMemInputPin, - * so we need to AddRef it to stop it being deleted while we are - * using it. Same with its filter. */ - pMemConnected = This->pMemInputPin; - IMemInputPin_AddRef(pMemConnected); - hr = IPin_QueryPinInfo(This->pin.pConnectedTo, &pinInfo); - } - } - LeaveCriticalSection(This->pin.pCritSec); - - if (SUCCEEDED(hr)) - { - /* NOTE: if we are in a critical section when Receive is called - * then it causes some problems (most notably with the native Video - * Renderer) if we are re-entered for whatever reason */ - hr = IMemInputPin_Receive(pMemConnected, pSample); - - /* If the filter's destroyed, tell upstream to stop sending data */ - if(IBaseFilter_Release(pinInfo.pFilter) == 0 && SUCCEEDED(hr)) - hr = S_FALSE; - } - if (pMemConnected) - IMemInputPin_Release(pMemConnected); - - return hr; -} - -HRESULT OutputPin_CommitAllocator(OutputPin * This) -{ - HRESULT hr = S_OK; - - TRACE("(%p)->()\n", This); - - EnterCriticalSection(This->pin.pCritSec); - { - if (!This->pin.pConnectedTo || !This->pMemInputPin) - hr = VFW_E_NOT_CONNECTED; - else - { - IMemAllocator * pAlloc = NULL; - - hr = IMemInputPin_GetAllocator(This->pMemInputPin, &pAlloc); - - if (SUCCEEDED(hr)) - hr = IMemAllocator_Commit(pAlloc); - - if (pAlloc) - IMemAllocator_Release(pAlloc); - } - } - LeaveCriticalSection(This->pin.pCritSec); - - TRACE("--> %08x\n", hr); - return hr; -} - -HRESULT OutputPin_DecommitAllocator(OutputPin * This) -{ - HRESULT hr = S_OK; - - TRACE("(%p)->()\n", This); - - EnterCriticalSection(This->pin.pCritSec); - { - if (!This->pin.pConnectedTo || !This->pMemInputPin) - hr = VFW_E_NOT_CONNECTED; - else - { - IMemAllocator * pAlloc = NULL; - - hr = IMemInputPin_GetAllocator(This->pMemInputPin, &pAlloc); - - if (SUCCEEDED(hr)) - hr = IMemAllocator_Decommit(pAlloc); - - if (pAlloc) - IMemAllocator_Release(pAlloc); - } - } - LeaveCriticalSection(This->pin.pCritSec); - - TRACE("--> %08x\n", hr); - return hr; -} - -HRESULT OutputPin_DeliverDisconnect(OutputPin * This) -{ - HRESULT hr; - - TRACE("(%p)->()\n", This); - - EnterCriticalSection(This->pin.pCritSec); - { - if (!This->pin.pConnectedTo || !This->pMemInputPin) - hr = VFW_E_NOT_CONNECTED; - else if (!This->custom_allocator) - { - IMemAllocator * pAlloc = NULL; - - hr = IMemInputPin_GetAllocator(This->pMemInputPin, &pAlloc); - - if (SUCCEEDED(hr)) - hr = IMemAllocator_Decommit(pAlloc); - - if (pAlloc) - IMemAllocator_Release(pAlloc); - - if (SUCCEEDED(hr)) - hr = IPin_Disconnect(This->pin.pConnectedTo); - } - else /* Kill the allocator! */ - { - hr = IPin_Disconnect(This->pin.pConnectedTo); - } - IPin_Disconnect((IPin *)This); - } - LeaveCriticalSection(This->pin.pCritSec); - - return hr; -} - /*** PullPin implementation ***/ static HRESULT PullPin_Init(const IPinVtbl *PullPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PULL pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, REQUESTPROC pCustomRequest, STOPPROCESSPROC pDone, LPCRITICAL_SECTION pCritSec, PullPin * pPinImpl) { /* Common attributes */ - pPinImpl->pin.lpVtbl = PullPin_Vtbl; + pPinImpl->pin.IPin_iface.lpVtbl = PullPin_Vtbl; pPinImpl->pin.refCount = 1; pPinImpl->pin.pConnectedTo = NULL; - pPinImpl->pin.fnQueryAccept = pQueryAccept; - pPinImpl->pin.pUserData = pUserData; pPinImpl->pin.pCritSec = pCritSec; Copy_PinInfo(&pPinImpl->pin.pinInfo, pPinInfo); ZeroMemory(&pPinImpl->pin.mtCurrent, sizeof(AM_MEDIA_TYPE)); /* Input pin attributes */ + pPinImpl->pUserData = pUserData; + pPinImpl->fnQueryAccept = pQueryAccept; pPinImpl->fnSampleProc = pSampleProc; pPinImpl->fnCleanProc = pCleanUp; pPinImpl->fnDone = pDone; pPinImpl->fnPreConnect = NULL; pPinImpl->pAlloc = NULL; + pPinImpl->prefAlloc = NULL; pPinImpl->pReader = NULL; pPinImpl->hThread = NULL; pPinImpl->hEventStateChanged = CreateEventW(NULL, TRUE, TRUE, NULL); @@ -1103,7 +240,7 @@ HRESULT PullPin_Construct(const IPinVtbl *PullPin_Vtbl, const PIN_INFO * pPinInf if (SUCCEEDED(PullPin_Init(PullPin_Vtbl, pPinInfo, pSampleProc, pUserData, pQueryAccept, pCleanUp, pCustomRequest, pDone, pCritSec, pPinImpl))) { - *ppPin = (IPin *)(&pPinImpl->pin.lpVtbl); + *ppPin = &pPinImpl->pin.IPin_iface; return S_OK; } @@ -1117,7 +254,7 @@ HRESULT WINAPI PullPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const { PIN_DIRECTION pindirReceive; HRESULT hr = S_OK; - PullPin *This = (PullPin *)iface; + PullPin *This = impl_PullPin_from_IPin(iface); TRACE("(%p/%p)->(%p, %p)\n", This, iface, pReceivePin, pmt); dump_AM_MEDIA_TYPE(pmt); @@ -1132,7 +269,7 @@ HRESULT WINAPI PullPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const props.cbAlign = 1; props.cbPrefix = 0; - if (SUCCEEDED(hr) && (This->pin.fnQueryAccept(This->pin.pUserData, pmt) != S_OK)) + if (SUCCEEDED(hr) && (This->fnQueryAccept(This->pUserData, pmt) != S_OK)) hr = VFW_E_TYPE_NOT_ACCEPTED; /* FIXME: shouldn't we just map common errors onto * VFW_E_TYPE_NOT_ACCEPTED and pass the value on otherwise? */ @@ -1149,6 +286,7 @@ HRESULT WINAPI PullPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const This->pReader = NULL; This->pAlloc = NULL; + This->prefAlloc = NULL; if (SUCCEEDED(hr)) { hr = IPin_QueryInterface(pReceivePin, &IID_IAsyncReader, (LPVOID *)&This->pReader); @@ -1159,9 +297,19 @@ HRESULT WINAPI PullPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const hr = This->fnPreConnect(iface, pReceivePin, &props); } + /* + * Some custom filters (such as the one used by Fallout 3 + * and Fallout: New Vegas) expect to be passed a non-NULL + * preferred allocator. + */ if (SUCCEEDED(hr)) { - hr = IAsyncReader_RequestAllocator(This->pReader, NULL, &props, &This->pAlloc); + hr = StdMemAllocator_create(NULL, (LPVOID *) &This->prefAlloc); + } + + if (SUCCEEDED(hr)) + { + hr = IAsyncReader_RequestAllocator(This->pReader, This->prefAlloc, &props, &This->pAlloc); } if (SUCCEEDED(hr)) @@ -1180,6 +328,9 @@ HRESULT WINAPI PullPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const if (This->pReader) IAsyncReader_Release(This->pReader); This->pReader = NULL; + if (This->prefAlloc) + IMemAllocator_Release(This->prefAlloc); + This->prefAlloc = NULL; if (This->pAlloc) IMemAllocator_Release(This->pAlloc); This->pAlloc = NULL; @@ -1193,7 +344,7 @@ HRESULT WINAPI PullPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const HRESULT WINAPI PullPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv) { - PullPin *This = (PullPin *)iface; + PullPin *This = impl_PullPin_from_IPin(iface); TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv); @@ -1203,9 +354,10 @@ HRESULT WINAPI PullPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv) *ppv = iface; else if (IsEqualIID(riid, &IID_IPin)) *ppv = iface; - else if (IsEqualIID(riid, &IID_IMediaSeeking)) + else if (IsEqualIID(riid, &IID_IMediaSeeking) || + IsEqualIID(riid, &IID_IQualityControl)) { - return IBaseFilter_QueryInterface(This->pin.pinInfo.pFilter, &IID_IMediaSeeking, ppv); + return IBaseFilter_QueryInterface(This->pin.pinInfo.pFilter, riid, ppv); } if (*ppv) @@ -1221,7 +373,7 @@ HRESULT WINAPI PullPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv) ULONG WINAPI PullPin_Release(IPin *iface) { - PullPin *This = (PullPin *)iface; + PullPin *This = impl_PullPin_from_IPin(iface); ULONG refCount = InterlockedDecrement(&This->pin.refCount); TRACE("(%p)->() Release from %d\n", This, refCount + 1); @@ -1231,6 +383,8 @@ ULONG WINAPI PullPin_Release(IPin *iface) WaitForSingleObject(This->hEventStateChanged, INFINITE); assert(!This->hThread); + if(This->prefAlloc) + IMemAllocator_Release(This->prefAlloc); if(This->pAlloc) IMemAllocator_Release(This->pAlloc); if(This->pReader) @@ -1252,6 +406,9 @@ static void PullPin_Flush(PullPin *This) if (This->pReader) { + /* Do not allow state to change while flushing */ + EnterCriticalSection(This->pin.pCritSec); + /* Flush outstanding samples */ IAsyncReader_BeginFlush(This->pReader); @@ -1270,6 +427,8 @@ static void PullPin_Flush(PullPin *This) } IAsyncReader_EndFlush(This->pReader); + + LeaveCriticalSection(This->pin.pCritSec); } } @@ -1290,12 +449,12 @@ static void PullPin_Thread_Process(PullPin *This) if (This->rtCurrent >= This->rtStop) { - IPin_EndOfStream((IPin *)This); + IPin_EndOfStream(&This->pin.IPin_iface); return; } /* There is no sample in our buffer */ - hr = This->fnCustomRequest(This->pin.pUserData); + hr = This->fnCustomRequest(This->pUserData); if (FAILED(hr)) ERR("Request error: %x\n", hr); @@ -1317,18 +476,19 @@ static void PullPin_Thread_Process(PullPin *This) /* Return an empty sample on error to the implementation in case it does custom parsing, so it knows it's gone */ if (SUCCEEDED(hr)) { - hr = This->fnSampleProc(This->pin.pUserData, pSample, dwUser); + hr = This->fnSampleProc(This->pUserData, pSample, dwUser); } else { - /* FIXME: This is not well handled yet! */ - ERR("Processing error: %x\n", hr); if (hr == VFW_E_TIMEOUT) { - assert(!pSample); + if (pSample != NULL) + WARN("Non-NULL sample returned with VFW_E_TIMEOUT.\n"); hr = S_OK; - continue; } + /* FIXME: Errors are not well handled yet! */ + else + ERR("Processing error: %x\n", hr); } if (pSample) @@ -1338,17 +498,29 @@ static void PullPin_Thread_Process(PullPin *This) } } while (This->rtCurrent < This->rtStop && hr == S_OK && !This->stop_playback); - /* Sample was rejected, and we are asked to terminate */ - if (pSample) + /* + * Sample was rejected, and we are asked to terminate. When there is more than one buffer + * it is possible for a filter to have several queued samples, making it necessary to + * release all of these pending samples. + */ + if (This->stop_playback || FAILED(hr)) { - IMediaSample_Release(pSample); + DWORD_PTR dwUser; + + do + { + if (pSample) + IMediaSample_Release(pSample); + pSample = NULL; + IAsyncReader_WaitForNext(This->pReader, 0, &pSample, &dwUser); + } while(pSample); } /* Can't reset state to Sleepy here because that might race, instead PauseProcessing will do that for us * Flush remaining samples */ if (This->fnDone) - This->fnDone(This->pin.pUserData); + This->fnDone(This->pUserData); TRACE("End: %08x, %d\n", hr, This->stop_playback); } @@ -1490,11 +662,27 @@ HRESULT PullPin_PauseProcessing(PullPin * This) assert(This->state == Req_Run|| This->state == Req_Sleepy); assert(WaitForSingleObject(This->thread_sleepy, 0) == WAIT_TIMEOUT); + This->state = Req_Pause; This->stop_playback = 1; ResetEvent(This->hEventStateChanged); SetEvent(This->thread_sleepy); + /* Release any outstanding samples */ + if (This->pReader) + { + IMediaSample *pSample; + DWORD_PTR dwUser; + + do + { + pSample = NULL; + IAsyncReader_WaitForNext(This->pReader, 0, &pSample, &dwUser); + if (pSample) + IMediaSample_Release(pSample); + } while(pSample); + } + LeaveCriticalSection(This->pin.pCritSec); } @@ -1527,16 +715,33 @@ HRESULT PullPin_WaitForStateChange(PullPin * This, DWORD dwMilliseconds) return S_OK; } +HRESULT WINAPI PullPin_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt) +{ + PullPin *This = impl_PullPin_from_IPin(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, pmt); + + return (This->fnQueryAccept(This->pUserData, pmt) == S_OK ? S_OK : S_FALSE); +} + HRESULT WINAPI PullPin_EndOfStream(IPin * iface) { - FIXME("(%p)->() stub\n", iface); + PullPin *This = impl_PullPin_from_IPin(iface); + HRESULT hr = S_FALSE; - return SendFurther( iface, deliver_endofstream, NULL, NULL ); + TRACE("(%p)->()\n", iface); + + EnterCriticalSection(This->pin.pCritSec); + hr = SendFurther( iface, deliver_endofstream, NULL, NULL ); + SetEvent(This->hEventStateChanged); + LeaveCriticalSection(This->pin.pCritSec); + + return hr; } HRESULT WINAPI PullPin_BeginFlush(IPin * iface) { - PullPin *This = (PullPin *)iface; + PullPin *This = impl_PullPin_from_IPin(iface); TRACE("(%p)->()\n", This); EnterCriticalSection(This->pin.pCritSec); @@ -1561,7 +766,7 @@ HRESULT WINAPI PullPin_BeginFlush(IPin * iface) EnterCriticalSection(This->pin.pCritSec); { - This->fnCleanProc(This->pin.pUserData); + This->fnCleanProc(This->pUserData); } LeaveCriticalSection(This->pin.pCritSec); @@ -1570,7 +775,7 @@ HRESULT WINAPI PullPin_BeginFlush(IPin * iface) HRESULT WINAPI PullPin_EndFlush(IPin * iface) { - PullPin *This = (PullPin *)iface; + PullPin *This = impl_PullPin_from_IPin(iface); TRACE("(%p)->()\n", iface); @@ -1601,7 +806,7 @@ HRESULT WINAPI PullPin_EndFlush(IPin * iface) HRESULT WINAPI PullPin_Disconnect(IPin *iface) { HRESULT hr; - PullPin *This = (PullPin *)iface; + PullPin *This = impl_PullPin_from_IPin(iface); TRACE("()\n"); @@ -1643,222 +848,21 @@ HRESULT WINAPI PullPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE static const IPinVtbl PullPin_Vtbl = { PullPin_QueryInterface, - IPinImpl_AddRef, + BasePinImpl_AddRef, PullPin_Release, - InputPin_Connect, + BaseInputPinImpl_Connect, PullPin_ReceiveConnection, PullPin_Disconnect, - IPinImpl_ConnectedTo, - IPinImpl_ConnectionMediaType, - IPinImpl_QueryPinInfo, - IPinImpl_QueryDirection, - IPinImpl_QueryId, - IPinImpl_QueryAccept, - IPinImpl_EnumMediaTypes, - IPinImpl_QueryInternalConnections, + BasePinImpl_ConnectedTo, + BasePinImpl_ConnectionMediaType, + BasePinImpl_QueryPinInfo, + BasePinImpl_QueryDirection, + BasePinImpl_QueryId, + PullPin_QueryAccept, + BasePinImpl_EnumMediaTypes, + BasePinImpl_QueryInternalConnections, PullPin_EndOfStream, PullPin_BeginFlush, PullPin_EndFlush, PullPin_NewSegment }; - -/*** The Construct functions ***/ - -/* Function called as a helper to IPin_Connect */ -/* specific AM_MEDIA_TYPE - it cannot be NULL */ -/* NOTE: not part of standard interface */ -static HRESULT OutputPin_ConnectSpecific(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) -{ - OutputPin *This = (OutputPin *)iface; - HRESULT hr; - IMemAllocator * pMemAlloc = NULL; - ALLOCATOR_PROPERTIES actual; /* FIXME: should we put the actual props back in to This? */ - - TRACE("(%p, %p)\n", pReceivePin, pmt); - dump_AM_MEDIA_TYPE(pmt); - - /* FIXME: call queryacceptproc */ - - This->pin.pConnectedTo = pReceivePin; - IPin_AddRef(pReceivePin); - CopyMediaType(&This->pin.mtCurrent, pmt); - - hr = IPin_ReceiveConnection(pReceivePin, iface, pmt); - - /* get the IMemInputPin interface we will use to deliver samples to the - * connected pin */ - if (SUCCEEDED(hr)) - { - This->pMemInputPin = NULL; - hr = IPin_QueryInterface(pReceivePin, &IID_IMemInputPin, (LPVOID)&This->pMemInputPin); - - if (SUCCEEDED(hr) && !This->custom_allocator) - { - hr = IMemInputPin_GetAllocator(This->pMemInputPin, &pMemAlloc); - - if (hr == VFW_E_NO_ALLOCATOR) - /* Input pin provides no allocator, use standard memory allocator */ - hr = CoCreateInstance(&CLSID_MemoryAllocator, NULL, CLSCTX_INPROC_SERVER, &IID_IMemAllocator, (LPVOID*)&pMemAlloc); - - if (SUCCEEDED(hr)) - hr = IMemAllocator_SetProperties(pMemAlloc, &This->allocProps, &actual); - - if (SUCCEEDED(hr)) - hr = IMemInputPin_NotifyAllocator(This->pMemInputPin, pMemAlloc, This->readonly); - - if (pMemAlloc) - IMemAllocator_Release(pMemAlloc); - } - else if (SUCCEEDED(hr)) - { - if (This->alloc) - { - hr = IMemInputPin_NotifyAllocator(This->pMemInputPin, This->alloc, This->readonly); - } - else - hr = VFW_E_NO_ALLOCATOR; - } - - /* break connection if we couldn't get the allocator */ - if (FAILED(hr)) - { - if (This->pMemInputPin) - IMemInputPin_Release(This->pMemInputPin); - This->pMemInputPin = NULL; - - IPin_Disconnect(pReceivePin); - } - } - - if (FAILED(hr)) - { - IPin_Release(This->pin.pConnectedTo); - This->pin.pConnectedTo = NULL; - FreeMediaType(&This->pin.mtCurrent); - } - - TRACE(" -- %x\n", hr); - return hr; -} - -static HRESULT InputPin_Init(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PUSH pSampleProc, LPVOID pUserData, - QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, LPCRITICAL_SECTION pCritSec, IMemAllocator *allocator, InputPin * pPinImpl) -{ - TRACE("\n"); - - /* Common attributes */ - pPinImpl->pin.refCount = 1; - pPinImpl->pin.pConnectedTo = NULL; - pPinImpl->pin.fnQueryAccept = pQueryAccept; - pPinImpl->pin.pUserData = pUserData; - pPinImpl->pin.pCritSec = pCritSec; - Copy_PinInfo(&pPinImpl->pin.pinInfo, pPinInfo); - ZeroMemory(&pPinImpl->pin.mtCurrent, sizeof(AM_MEDIA_TYPE)); - - /* Input pin attributes */ - pPinImpl->fnSampleProc = pSampleProc; - pPinImpl->fnCleanProc = pCleanUp; - pPinImpl->pAllocator = pPinImpl->preferred_allocator = allocator; - if (pPinImpl->preferred_allocator) - IMemAllocator_AddRef(pPinImpl->preferred_allocator); - pPinImpl->tStart = 0; - pPinImpl->tStop = 0; - pPinImpl->dRate = 1.0; - pPinImpl->pin.lpVtbl = InputPin_Vtbl; - pPinImpl->lpVtblMemInput = &MemInputPin_Vtbl; - pPinImpl->flushing = pPinImpl->end_of_stream = 0; - - return S_OK; -} - -static HRESULT OutputPin_Init(const IPinVtbl *OutputPin_Vtbl, const PIN_INFO * pPinInfo, const ALLOCATOR_PROPERTIES * props, LPVOID pUserData, - QUERYACCEPTPROC pQueryAccept, LPCRITICAL_SECTION pCritSec, OutputPin * pPinImpl) -{ - TRACE("\n"); - - /* Common attributes */ - pPinImpl->pin.lpVtbl = OutputPin_Vtbl; - pPinImpl->pin.refCount = 1; - pPinImpl->pin.pConnectedTo = NULL; - pPinImpl->pin.fnQueryAccept = pQueryAccept; - pPinImpl->pin.pUserData = pUserData; - pPinImpl->pin.pCritSec = pCritSec; - Copy_PinInfo(&pPinImpl->pin.pinInfo, pPinInfo); - ZeroMemory(&pPinImpl->pin.mtCurrent, sizeof(AM_MEDIA_TYPE)); - - /* Output pin attributes */ - pPinImpl->pMemInputPin = NULL; - pPinImpl->pConnectSpecific = OutputPin_ConnectSpecific; - /* If custom_allocator is set, you will need to specify an allocator - * in the alloc member of the struct before an output pin can connect - */ - pPinImpl->custom_allocator = 0; - pPinImpl->alloc = NULL; - pPinImpl->readonly = FALSE; - if (props) - { - pPinImpl->allocProps = *props; - if (pPinImpl->allocProps.cbAlign == 0) - pPinImpl->allocProps.cbAlign = 1; - } - else - ZeroMemory(&pPinImpl->allocProps, sizeof(pPinImpl->allocProps)); - - return S_OK; -} - -HRESULT InputPin_Construct(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PUSH pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, LPCRITICAL_SECTION pCritSec, IMemAllocator *allocator, IPin ** ppPin) -{ - InputPin * pPinImpl; - - *ppPin = NULL; - - if (pPinInfo->dir != PINDIR_INPUT) - { - ERR("Pin direction(%x) != PINDIR_INPUT\n", pPinInfo->dir); - return E_INVALIDARG; - } - - pPinImpl = CoTaskMemAlloc(sizeof(*pPinImpl)); - - if (!pPinImpl) - return E_OUTOFMEMORY; - - if (SUCCEEDED(InputPin_Init(InputPin_Vtbl, pPinInfo, pSampleProc, pUserData, pQueryAccept, pCleanUp, pCritSec, allocator, pPinImpl))) - { - *ppPin = (IPin *)pPinImpl; - return S_OK; - } - - CoTaskMemFree(pPinImpl); - return E_FAIL; -} - -HRESULT OutputPin_Construct(const IPinVtbl *OutputPin_Vtbl, LONG outputpin_size, const PIN_INFO * pPinInfo, ALLOCATOR_PROPERTIES *props, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, LPCRITICAL_SECTION pCritSec, IPin ** ppPin) -{ - OutputPin * pPinImpl; - - *ppPin = NULL; - - if (pPinInfo->dir != PINDIR_OUTPUT) - { - ERR("Pin direction(%x) != PINDIR_OUTPUT\n", pPinInfo->dir); - return E_INVALIDARG; - } - - assert(outputpin_size >= sizeof(OutputPin)); - - pPinImpl = CoTaskMemAlloc(outputpin_size); - - if (!pPinImpl) - return E_OUTOFMEMORY; - - if (SUCCEEDED(OutputPin_Init(OutputPin_Vtbl, pPinInfo, props, pUserData, pQueryAccept, pCritSec, pPinImpl))) - { - *ppPin = (IPin *)(&pPinImpl->pin.lpVtbl); - return S_OK; - } - - CoTaskMemFree(pPinImpl); - return E_FAIL; -} diff --git a/reactos/dll/directx/quartz/pin.h b/reactos/dll/directx/quartz/pin.h index e356ef32f53..428fa6fe8e4 100644 --- a/reactos/dll/directx/quartz/pin.h +++ b/reactos/dll/directx/quartz/pin.h @@ -24,7 +24,6 @@ * Cookie is the cookie that was set when requesting the buffer, if you don't * implement custom requesting, you can safely ignore this */ -typedef HRESULT (* SAMPLEPROC_PUSH)(LPVOID userdata, IMediaSample * pSample); typedef HRESULT (* SAMPLEPROC_PULL)(LPVOID userdata, IMediaSample * pSample, DWORD_PTR cookie); /* This function will determine whether a type is supported or not. @@ -66,56 +65,17 @@ typedef HRESULT (* STOPPROCESSPROC) (LPVOID userdata); #define ALIGNDOWN(value,boundary) ((value)/(boundary)*(boundary)) #define ALIGNUP(value,boundary) (ALIGNDOWN((value)+(boundary)-1, (boundary))) -typedef struct IPinImpl -{ - const struct IPinVtbl * lpVtbl; - LONG refCount; - LPCRITICAL_SECTION pCritSec; - PIN_INFO pinInfo; - IPin * pConnectedTo; - AM_MEDIA_TYPE mtCurrent; - ENUMMEDIADETAILS enumMediaDetails; - QUERYACCEPTPROC fnQueryAccept; - LPVOID pUserData; -} IPinImpl; - -typedef struct InputPin -{ - /* inheritance C style! */ - IPinImpl pin; - - const IMemInputPinVtbl * lpVtblMemInput; - IMemAllocator * pAllocator; - SAMPLEPROC_PUSH fnSampleProc; - CLEANUPPROC fnCleanProc; - REFERENCE_TIME tStart; - REFERENCE_TIME tStop; - double dRate; - BOOL flushing, end_of_stream; - IMemAllocator *preferred_allocator; -} InputPin; - -typedef struct OutputPin -{ - /* inheritance C style! */ - IPinImpl pin; - - IMemInputPin * pMemInputPin; - HRESULT (* pConnectSpecific)(IPin * iface, IPin * pReceiver, const AM_MEDIA_TYPE * pmt); - BOOL custom_allocator; - IMemAllocator *alloc; - BOOL readonly; - ALLOCATOR_PROPERTIES allocProps; -} OutputPin; - typedef struct PullPin { /* inheritance C style! */ - IPinImpl pin; + BasePin pin; + LPVOID pUserData; REFERENCE_TIME rtStart, rtCurrent, rtNext, rtStop; IAsyncReader * pReader; + IMemAllocator * prefAlloc; IMemAllocator * pAlloc; + QUERYACCEPTPROC fnQueryAccept; SAMPLEPROC_PULL fnSampleProc; PRECONNECTPROC fnPreConnect; REQUESTPROC fnCustomRequest; @@ -142,58 +102,18 @@ typedef struct PullPin #define Req_Pause 3 /*** Constructors ***/ -HRESULT InputPin_Construct(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PUSH pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, LPCRITICAL_SECTION pCritSec, IMemAllocator *, IPin ** ppPin); -HRESULT OutputPin_Construct(const IPinVtbl *OutputPin_Vtbl, LONG outputpin_size, const PIN_INFO * pPinInfo, ALLOCATOR_PROPERTIES *props, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, LPCRITICAL_SECTION pCritSec, IPin ** ppPin); HRESULT PullPin_Construct(const IPinVtbl *PullPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PULL pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, STOPPROCESSPROC, REQUESTPROC pCustomRequest, LPCRITICAL_SECTION pCritSec, IPin ** ppPin); /**************************/ /*** Pin Implementation ***/ -/* Common */ -ULONG WINAPI IPinImpl_AddRef(IPin * iface); -HRESULT WINAPI IPinImpl_Disconnect(IPin * iface); -HRESULT WINAPI IPinImpl_ConnectedTo(IPin * iface, IPin ** ppPin); -HRESULT WINAPI IPinImpl_ConnectionMediaType(IPin * iface, AM_MEDIA_TYPE * pmt); -HRESULT WINAPI IPinImpl_QueryPinInfo(IPin * iface, PIN_INFO * pInfo); -HRESULT WINAPI IPinImpl_QueryDirection(IPin * iface, PIN_DIRECTION * pPinDir); -HRESULT WINAPI IPinImpl_QueryId(IPin * iface, LPWSTR * Id); -HRESULT WINAPI IPinImpl_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt); -HRESULT WINAPI IPinImpl_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum); -HRESULT WINAPI IPinImpl_QueryInternalConnections(IPin * iface, IPin ** apPin, ULONG * cPin); - -/* Input Pin */ -HRESULT WINAPI InputPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv); -ULONG WINAPI InputPin_Release(IPin * iface); -HRESULT WINAPI InputPin_Connect(IPin * iface, IPin * pConnector, const AM_MEDIA_TYPE * pmt); -HRESULT WINAPI InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt); -HRESULT WINAPI InputPin_EndOfStream(IPin * iface); -HRESULT WINAPI InputPin_BeginFlush(IPin * iface); -HRESULT WINAPI InputPin_EndFlush(IPin * iface); -HRESULT WINAPI InputPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate); - -/* Output Pin */ -HRESULT WINAPI OutputPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv); -ULONG WINAPI OutputPin_Release(IPin * iface); -HRESULT WINAPI OutputPin_Connect(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt); -HRESULT WINAPI OutputPin_Disconnect(IPin * iface); -HRESULT WINAPI OutputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt); -HRESULT WINAPI OutputPin_EndOfStream(IPin * iface); -HRESULT WINAPI OutputPin_BeginFlush(IPin * iface); -HRESULT WINAPI OutputPin_EndFlush(IPin * iface); -HRESULT WINAPI OutputPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate); - -HRESULT OutputPin_CommitAllocator(OutputPin * This); -HRESULT OutputPin_DecommitAllocator(OutputPin * This); -HRESULT OutputPin_GetDeliveryBuffer(OutputPin * This, IMediaSample ** ppSample, REFERENCE_TIME * tStart, REFERENCE_TIME * tStop, DWORD dwFlags); -HRESULT OutputPin_SendSample(OutputPin * This, IMediaSample * pSample); -HRESULT OutputPin_DeliverDisconnect(OutputPin * This); - /* Pull Pin */ HRESULT WINAPI PullPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt); HRESULT WINAPI PullPin_Disconnect(IPin * iface); HRESULT WINAPI PullPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv); ULONG WINAPI PullPin_Release(IPin * iface); HRESULT WINAPI PullPin_EndOfStream(IPin * iface); +HRESULT WINAPI PullPin_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt); HRESULT WINAPI PullPin_BeginFlush(IPin * iface); HRESULT WINAPI PullPin_EndFlush(IPin * iface); HRESULT WINAPI PullPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate); @@ -202,3 +122,9 @@ HRESULT WINAPI PullPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE HRESULT PullPin_StartProcessing(PullPin * This); HRESULT PullPin_PauseProcessing(PullPin * This); HRESULT PullPin_WaitForStateChange(PullPin * This, DWORD dwMilliseconds); + +/* COM helpers */ +static inline PullPin *impl_PullPin_from_IPin( IPin *iface ) +{ + return CONTAINING_RECORD(iface, PullPin, pin.IPin_iface); +} diff --git a/reactos/dll/directx/quartz/quartz_private.h b/reactos/dll/directx/quartz/quartz_private.h index a5073a7ff2a..3fb620484dc 100644 --- a/reactos/dll/directx/quartz/quartz_private.h +++ b/reactos/dll/directx/quartz/quartz_private.h @@ -2,9 +2,6 @@ * * Copyright 2002 Lionel Ulmer * - * This file contains the (internal) driver registration functions, - * driver enumeration APIs and DirectDraw creation functions. - * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -39,6 +36,7 @@ #include #include #include +#include #include #define MEDIATIME_FROM_BYTES(x) ((LONGLONG)(x) * 10000000) @@ -46,60 +44,35 @@ #define BYTES_FROM_MEDIATIME(time) SEC_FROM_MEDIATIME(time) #define MSEC_FROM_MEDIATIME(time) ((time) / 10000) -#define ICOM_THIS_MULTI(impl,field,iface) impl* const This=(impl*)((char*)(iface) - offsetof(impl,field)) +HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj) DECLSPEC_HIDDEN; +HRESULT FilterGraphNoThread_create(IUnknown *pUnkOuter, LPVOID *ppObj) DECLSPEC_HIDDEN; +HRESULT FilterMapper2_create(IUnknown *pUnkOuter, LPVOID *ppObj) DECLSPEC_HIDDEN; +HRESULT FilterMapper_create(IUnknown *pUnkOuter, LPVOID *ppObj) DECLSPEC_HIDDEN; +HRESULT AsyncReader_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN; +HRESULT StdMemAllocator_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN; +HRESULT AVISplitter_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN; +HRESULT MPEGSplitter_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN; +HRESULT AVIDec_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN; +HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN; +HRESULT VideoRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN; +HRESULT NullRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN; +HRESULT VideoRendererDefault_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN; +HRESULT QUARTZ_CreateSystemClock(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN; +HRESULT ACMWrapper_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN; +HRESULT WAVEParser_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN; +HRESULT VMR9Impl_create(IUnknown *pUnkOuter, LPVOID *ppv) DECLSPEC_HIDDEN; -HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj); -HRESULT FilterGraphNoThread_create(IUnknown *pUnkOuter, LPVOID *ppObj); -HRESULT FilterMapper2_create(IUnknown *pUnkOuter, LPVOID *ppObj); -HRESULT FilterMapper_create(IUnknown *pUnkOuter, LPVOID *ppObj); -HRESULT AsyncReader_create(IUnknown * pUnkOuter, LPVOID * ppv); -HRESULT StdMemAllocator_create(IUnknown * pUnkOuter, LPVOID * ppv); -HRESULT AVISplitter_create(IUnknown * pUnkOuter, LPVOID * ppv); -HRESULT MPEGSplitter_create(IUnknown * pUnkOuter, LPVOID * ppv); -HRESULT AVIDec_create(IUnknown * pUnkOuter, LPVOID * ppv); -HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv); -HRESULT VideoRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv); -HRESULT NullRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv); -HRESULT VideoRendererDefault_create(IUnknown * pUnkOuter, LPVOID * ppv); -HRESULT QUARTZ_CreateSystemClock(IUnknown * pUnkOuter, LPVOID * ppv); -HRESULT ACMWrapper_create(IUnknown * pUnkOuter, LPVOID * ppv); -HRESULT WAVEParser_create(IUnknown * pUnkOuter, LPVOID * ppv); -HRESULT SeekingPassThru_create(IUnknown *pUnkOuter, LPVOID *ppObj); +HRESULT EnumMonikerImpl_Create(IMoniker ** ppMoniker, ULONG nMonikerCount, IEnumMoniker ** ppEnum) DECLSPEC_HIDDEN; -HRESULT EnumMonikerImpl_Create(IMoniker ** ppMoniker, ULONG nMonikerCount, IEnumMoniker ** ppEnum); +HRESULT IEnumRegFiltersImpl_Construct(REGFILTER * pInRegFilters, const ULONG size, IEnumRegFilters ** ppEnum) DECLSPEC_HIDDEN; +HRESULT IEnumFiltersImpl_Construct(IGraphVersion * pVersionSource, IBaseFilter *** pppFilters, ULONG * pNumFilters, IEnumFilters ** ppEnum) DECLSPEC_HIDDEN; -typedef struct tagENUMEDIADETAILS -{ - ULONG cMediaTypes; - AM_MEDIA_TYPE * pMediaTypes; -} ENUMMEDIADETAILS; +extern const char * qzdebugstr_guid(const GUID * id) DECLSPEC_HIDDEN; +extern void video_unregister_windowclass(void) DECLSPEC_HIDDEN; -typedef HRESULT (* FNOBTAINPIN)(IBaseFilter *iface, ULONG pos, IPin **pin, DWORD *lastsynctick); - -HRESULT IEnumPinsImpl_Construct(IEnumPins ** ppEnum, FNOBTAINPIN receive_pin, IBaseFilter *base); -HRESULT IEnumMediaTypesImpl_Construct(const ENUMMEDIADETAILS * pDetails, IEnumMediaTypes ** ppEnum); -HRESULT IEnumRegFiltersImpl_Construct(REGFILTER * pInRegFilters, const ULONG size, IEnumRegFilters ** ppEnum); -HRESULT IEnumFiltersImpl_Construct(IBaseFilter ** ppFilters, ULONG nFilters, IEnumFilters ** ppEnum); - -extern const char * qzdebugstr_guid(const GUID * id); - -HRESULT CopyMediaType(AM_MEDIA_TYPE * pDest, const AM_MEDIA_TYPE *pSrc); -void FreeMediaType(AM_MEDIA_TYPE * pmt); -void DeleteMediaType(AM_MEDIA_TYPE * pmt); BOOL CompareMediaTypes(const AM_MEDIA_TYPE * pmt1, const AM_MEDIA_TYPE * pmt2, BOOL bWildcards); -void dump_AM_MEDIA_TYPE(const AM_MEDIA_TYPE * pmt); -HRESULT updatehres( HRESULT original, HRESULT new ); +void dump_AM_MEDIA_TYPE(const AM_MEDIA_TYPE * pmt) DECLSPEC_HIDDEN; -typedef struct StdMediaSample2 -{ - const IMediaSample2Vtbl * lpvtbl; - - LONG ref; - AM_SAMPLE2_PROPERTIES props; - IMemAllocator * pParent; - struct list listentry; - LONGLONG tMediaStart; - LONGLONG tMediaEnd; -} StdMediaSample2; +HRESULT GetClassMediaFile(IAsyncReader * pReader, LPCOLESTR pszFileName, GUID * majorType, GUID * minorType, GUID * sourceFilter); #endif /* __QUARTZ_PRIVATE_INCLUDED__ */ diff --git a/reactos/dll/directx/quartz/quartz_strmif.idl b/reactos/dll/directx/quartz/quartz_strmif.idl index aad62321f27..ed7abe6b21a 100644 --- a/reactos/dll/directx/quartz/quartz_strmif.idl +++ b/reactos/dll/directx/quartz/quartz_strmif.idl @@ -16,7 +16,144 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -/* just a wrapper for strmif.idl */ - cpp_quote("#include ") #include "strmif.idl" + +[ + threading(both), + uuid(670d1d20-a068-11d0-b3f0-00aa003761c5) /* IAMCopyCaptureFileProgress */ +] +coclass PSFactoryBuffer { interface IFactoryBuffer; } + +[ + helpstring("Filter Graph"), + threading(both), + uuid(e436ebb3-524f-11ce-9f53-0020af0ba770) +] +coclass FilterGraph { interface IFilterGraph2; } + +[ + helpstring("Filter Graph no thread"), + threading(both), + uuid(e436ebb8-524f-11ce-9f53-0020af0ba770) +] +coclass FilterGraphNoThread { interface IFilterGraph2; } + +[ + helpstring("Filter Mapper"), + threading(both), + uuid(e436ebb2-524f-11ce-9f53-0020af0ba770) +] +coclass FilterMapper { interface IFilterMapper; } + +[ + helpstring("Filter Mapper2"), + threading(both), + uuid(cda42200-bd88-11d0-bd4e-00a0c911ce86) +] +coclass FilterMapper2 { interface IFilterMapper3; } + +[ + helpstring("System Clock"), + threading(both), + uuid(e436ebb1-524f-11ce-9f53-0020af0ba770) +] +coclass SystemClock { interface IReferenceClock; } + +[ + helpstring("Memory Allocator"), + threading(both), + uuid(1e651cc0-b199-11d0-8212-00c04fc32c45) +] +coclass MemoryAllocator { interface IMemAllocator; } + +[ + helpstring("Seeking"), + threading(both), + uuid(060af76c-68dd-11d0-8fc1-00c04fd9189d) +] +coclass SeekingPassThru { interface ISeekingPassThru; } + +[ + helpstring("File Source Filter"), + threading(both), + uuid(e436ebb5-524f-11ce-9f53-0020af0ba770) +] +coclass AsyncReader { interface IBaseFilter; } + +[ + helpstring("AVI Splitter"), + threading(both), + uuid(1b544c20-fd0b-11ce-8c63-00aa0044b51e) +] +coclass AviSplitter { interface IBaseFilter; } + +[ + helpstring("MPEG-I Stream Splitter"), + threading(both), + uuid(336475d0-942a-11ce-a870-00aa002feab5) +] +coclass MPEG1Splitter { interface IBaseFilter; } + +[ + helpstring("AVI Decompressor"), + threading(both), + uuid(cf49d4e0-1115-11ce-b03a-0020af0ba770) +] +coclass AVIDec { interface IBaseFilter; } + +[ + helpstring("DirectSound Audio Renderer"), + threading(both), + uuid(79376820-07d0-11cf-a24d-0020afd79767) +] +coclass DSoundRender { interface IBaseFilter; } + +[ + helpstring("Wave Audio Renderer"), + threading(both), + uuid(e30629d1-27e5-11ce-875d-00608cb78066) +] +coclass AudioRender { interface IBaseFilter; } + +[ + helpstring("Null Renderer"), + threading(both), + uuid(c1f400a4-3f08-11d3-9f0b-006008039e37) +] +coclass NullRenderer { interface IBaseFilter; } + +[ + helpstring("Video Renderer"), + threading(both), + uuid(70e102b0-5556-11ce-97c0-00aa0055595a) +] +coclass VideoRenderer { interface IBaseFilter; } + +[ + helpstring("Default Video Renderer"), + threading(both), + uuid(6bc1cffa-8fc1-4261-ac22-cfb4cc38db50) +] +coclass VideoRendererDefault { interface IBaseFilter; } + +[ + helpstring("ACM wrapper"), + threading(both), + uuid(6a08cf80-0e18-11cf-a24d-0020afd79767) +] +coclass ACMWrapper { interface IBaseFilter; } + +[ + helpstring("Wave Parser"), + threading(both), + uuid(d51bd5a1-7548-11cf-a520-0080c77ef58a) +] +coclass WAVEParser { interface IBaseFilter; } + +[ + helpstring("Video Mixing Renderer 9"), + threading(both), + uuid(51b4abf3-748f-4e3b-a276-c828330e926a) +] +coclass VideoMixingRenderer9 { interface IBaseFilter; } diff --git a/reactos/dll/directx/quartz/quartz_strmif.rgs b/reactos/dll/directx/quartz/quartz_strmif.rgs new file mode 100644 index 00000000000..69c6a05c7fa --- /dev/null +++ b/reactos/dll/directx/quartz/quartz_strmif.rgs @@ -0,0 +1,269 @@ +HKCR +{ + NoRemove Interface + { + '{29840822-5B84-11D0-BD3B-00A0C911CE86}' = s 'ICreateDevEnum' + { + NumMethods = s 4 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{56A86891-0AD4-11CE-B03A-0020AF0BA770}' = s 'IPin' + { + NumMethods = s 18 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{56A86892-0AD4-11CE-B03A-0020AF0BA770}' = s 'IEnumPins' + { + NumMethods = s 7 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{89C31040-846B-11CE-97D3-00AA0055595A}' = s 'IEnumMediaTypes' + { + NumMethods = s 7 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{56A8689F-0AD4-11CE-B03A-0020AF0BA770}' = s 'IFilterGraph' + { + NumMethods = s 11 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{56A86893-0AD4-11CE-B03A-0020AF0BA770}' = s 'IEnumFilters' + { + NumMethods = s 7 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{56A86899-0AD4-11CE-B03A-0020AF0BA770}' = s 'IMediaFilter' + { + NumMethods = s 10 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{56A86895-0AD4-11CE-B03A-0020AF0BA770}' = s 'IBaseFilter' + { + NumMethods = s 15 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{56A86897-0AD4-11CE-B03A-0020AF0BA770}' = s 'IReferenceClock' + { + NumMethods = s 7 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{56A8689C-0AD4-11CE-B03A-0020AF0BA770}' = s 'IMemAllocator' + { + NumMethods = s 9 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{379A0CF0-C1DE-11D2-ABF5-00A0C905F375}' = s 'IMemAllocatorCallbackTemp' + { + NumMethods = s 11 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{92980B30-C1DE-11D2-ABF5-00A0C905F375}' = s 'IMemAllocatorNotifyCallbackTemp' + { + NumMethods = s 4 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{56A8689D-0AD4-11CE-B03A-0020AF0BA770}' = s 'IMemInputPin' + { + NumMethods = s 9 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{A3D8CEC0-7E5A-11CF-BBC5-00805F6CEF20}' = s 'IAMovieSetup' + { + NumMethods = s 5 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{36B73880-C2C8-11CF-8B46-00805F6CEF60}' = s 'IMediaSeeking' + { + NumMethods = s 20 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{56A868A4-0AD4-11CE-B03A-0020AF0BA770}' = s 'IEnumRegFilters' + { + NumMethods = s 7 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{56A868A3-0AD4-11CE-B03A-0020AF0BA770}' = s 'IFilterMapper' + { + NumMethods = s 11 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{B79BB0B0-33C1-11D1-ABE1-00A0C905F375}' = s 'IFilterMapper2' + { + NumMethods = s 7 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{B79BB0B1-33C1-11D1-ABE1-00A0C905F375}' = s 'IFilterMapper3' + { + NumMethods = s 8 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{56A868A5-0AD4-11CE-B03A-0020AF0BA770}' = s 'IQualityControl' + { + NumMethods = s 5 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{56A868A2-0AD4-11CE-B03A-0020AF0BA770}' = s 'IMediaEventSink' + { + NumMethods = s 4 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{56A868A6-0AD4-11CE-B03A-0020AF0BA770}' = s 'IFileSourceFilter' + { + NumMethods = s 5 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{A2104830-7C70-11CF-8BCE-00AA00A3F1A6}' = s 'IFileSinkFilter' + { + NumMethods = s 5 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{00855B90-CE1B-11D0-BD4F-00A0C911CE86}' = s 'IFileSinkFilter2' + { + NumMethods = s 7 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{56A868A9-0AD4-11CE-B03A-0020AF0BA770}' = s 'IGraphBuilder' + { + NumMethods = s 18 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{BF87B6E0-8C27-11D0-B3F0-00AA003761C5}' = s 'ICaptureGraphBuilder' + { + NumMethods = s 11 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{670D1D20-A068-11D0-B3F0-00AA003761C5}' = s 'IAMCopyCaptureFileProgress' + { + NumMethods = s 4 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{93E5A4E0-2D50-11D2-ABFA-00A0C9C6E38D}' = s 'ICaptureGraphBuilder2' + { + NumMethods = s 12 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{36B73882-C2C8-11CF-8B46-00805F6CEF60}' = s 'IFilterGraph2' + { + NumMethods = s 21 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{C6E13340-30AC-11D0-A18C-00A0C9118956}' = s 'IAMStreamConfig' + { + NumMethods = s 7 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{C6E13360-30AC-11D0-A18C-00A0C9118956}' = s 'IAMVideoProcAmp' + { + NumMethods = s 6 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{56A868AA-0AD4-11CE-B03A-0020AF0BA770}' = s 'IAsyncReader' + { + NumMethods = s 11 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{56A868AB-0AD4-11CE-B03A-0020AF0BA770}' = s 'IGraphVersion' + { + NumMethods = s 4 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{56A868AD-0AD4-11CE-B03A-0020AF0BA770}' = s 'IResourceConsumer' + { + NumMethods = s 5 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{56A868AC-0AD4-11CE-B03A-0020AF0BA770}' = s 'IResourceManager' + { + NumMethods = s 11 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + '{36B73883-C2C8-11CF-8B46-00805F6CEF60}' = s 'ISeekingPassThru' + { + NumMethods = s 4 + ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}' + } + } + NoRemove CLSID + { + '{670D1D20-A068-11D0-B3F0-00AA003761C5}' = s 'PSFactoryBuffer' + { + InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' } + } + '{E436EBB3-524F-11CE-9F53-0020AF0BA770}' = s 'Filter Graph' + { + InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' } + } + '{E436EBB8-524F-11CE-9F53-0020AF0BA770}' = s 'Filter Graph no thread' + { + InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' } + } + '{E436EBB2-524F-11CE-9F53-0020AF0BA770}' = s 'Filter Mapper' + { + InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' } + } + '{CDA42200-BD88-11D0-BD4E-00A0C911CE86}' = s 'Filter Mapper2' + { + InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' } + } + '{E436EBB1-524F-11CE-9F53-0020AF0BA770}' = s 'System Clock' + { + InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' } + } + '{1E651CC0-B199-11D0-8212-00C04FC32C45}' = s 'Memory Allocator' + { + InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' } + } + '{060AF76C-68DD-11D0-8FC1-00C04FD9189D}' = s 'Seeking' + { + InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' } + } + '{E436EBB5-524F-11CE-9F53-0020AF0BA770}' = s 'File Source Filter' + { + InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' } + } + '{1B544C20-FD0B-11CE-8C63-00AA0044B51E}' = s 'AVI Splitter' + { + InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' } + } + '{336475D0-942A-11CE-A870-00AA002FEAB5}' = s 'MPEG-I Stream Splitter' + { + InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' } + } + '{CF49D4E0-1115-11CE-B03A-0020AF0BA770}' = s 'AVI Decompressor' + { + InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' } + } + '{79376820-07D0-11CF-A24D-0020AFD79767}' = s 'DirectSound Audio Renderer' + { + InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' } + } + '{E30629D1-27E5-11CE-875D-00608CB78066}' = s 'Wave Audio Renderer' + { + InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' } + } + '{C1F400A4-3F08-11D3-9F0B-006008039E37}' = s 'Null Renderer' + { + InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' } + } + '{70E102B0-5556-11CE-97C0-00AA0055595A}' = s 'Video Renderer' + { + InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' } + } + '{6BC1CFFA-8FC1-4261-AC22-CFB4CC38DB50}' = s 'Default Video Renderer' + { + InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' } + } + '{6A08CF80-0E18-11CF-A24D-0020AFD79767}' = s 'ACM wrapper' + { + InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' } + } + '{D51BD5A1-7548-11CF-A520-0080C77EF58A}' = s 'Wave Parser' + { + InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' } + } + '{51B4ABF3-748F-4E3B-A276-C828330E926A}' = s 'Video Mixing Renderer 9' + { + InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' } + } + } +} diff --git a/reactos/dll/directx/quartz/regsvr.c b/reactos/dll/directx/quartz/regsvr.c index b5ec6ea7674..1b802c8af93 100644 --- a/reactos/dll/directx/quartz/regsvr.c +++ b/reactos/dll/directx/quartz/regsvr.c @@ -129,43 +129,43 @@ static HRESULT unregister_filters(struct regsvr_filter const *list); /*********************************************************************** * static string constants */ -static WCHAR const interface_keyname[10] = { +static const WCHAR interface_keyname[] = { 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 }; -static WCHAR const base_ifa_keyname[14] = { +static const WCHAR base_ifa_keyname[] = { 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 }; -static WCHAR const num_methods_keyname[11] = { +static const WCHAR num_methods_keyname[] = { 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 }; -static WCHAR const ps_clsid_keyname[15] = { +static const WCHAR ps_clsid_keyname[] = { 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's', 'i', 'd', 0 }; -static WCHAR const ps_clsid32_keyname[17] = { +static const WCHAR ps_clsid32_keyname[] = { 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's', 'i', 'd', '3', '2', 0 }; -static WCHAR const clsid_keyname[6] = { +static const WCHAR clsid_keyname[] = { 'C', 'L', 'S', 'I', 'D', 0 }; -static WCHAR const curver_keyname[7] = { +static const WCHAR curver_keyname[] = { 'C', 'u', 'r', 'V', 'e', 'r', 0 }; -static WCHAR const ips_keyname[13] = { +static const WCHAR ips_keyname[] = { 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r', 0 }; -static WCHAR const ips32_keyname[15] = { +static const WCHAR ips32_keyname[] = { 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r', '3', '2', 0 }; -static WCHAR const progid_keyname[7] = { +static const WCHAR progid_keyname[] = { 'P', 'r', 'o', 'g', 'I', 'D', 0 }; -static WCHAR const viprogid_keyname[25] = { +static const WCHAR viprogid_keyname[] = { 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D', 0 }; -static char const tmodel_valuename[] = "ThreadingModel"; -static WCHAR const mediatype_name[11] = { +static const char tmodel_valuename[] = "ThreadingModel"; +static const WCHAR mediatype_name[] = { 'M', 'e', 'd', 'i', 'a', ' ', 'T', 'y', 'p', 'e', 0 }; -static WCHAR const subtype_valuename[8] = { +static const WCHAR subtype_valuename[] = { 'S', 'u', 'b', 't', 'y', 'p', 'e', 0 }; -static WCHAR const sourcefilter_valuename[14] = { +static const WCHAR sourcefilter_valuename[] = { 'S', 'o', 'u', 'r', 'c', 'e', ' ', 'F', 'i', 'l', 't', 'e', 'r', 0 }; -static WCHAR const extensions_keyname[11] = { +static const WCHAR extensions_keyname[] = { 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', 0 }; /*********************************************************************** @@ -214,7 +214,7 @@ static HRESULT register_interfaces(struct regsvr_interface const *list) } if (0 <= list->num_methods) { - static WCHAR const fmt[3] = { '%', 'd', 0 }; + static const WCHAR fmt[] = { '%', 'd', 0 }; HKEY key; res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0, @@ -595,8 +595,8 @@ static HRESULT register_filters(struct regsvr_filter const *list) for (i = 0; list->pins[i].flags != 0xFFFFFFFF; i++) ; rf2.dwVersion = 2; rf2.dwMerit = list->merit; - rf2.u.s1.cPins2 = i; - rf2.u.s1.rgPins2 = prfp2 = CoTaskMemAlloc(i*sizeof(REGFILTERPINS2)); + rf2.u.s2.cPins2 = i; + rf2.u.s2.rgPins2 = prfp2 = CoTaskMemAlloc(i*sizeof(REGFILTERPINS2)); if (!prfp2) { hr = E_OUTOFMEMORY; break; @@ -783,121 +783,10 @@ error_close_progid_key: return res; } -static GUID const CLSID_PSFactoryBuffer = { - 0x92a3a302, 0xda7c, 0x4a1f, {0xba,0x7e,0x18,0x02,0xbb,0x5d,0x2d,0x02} }; - /*********************************************************************** * coclass list */ static struct regsvr_coclass const coclass_list[] = { - { &CLSID_FilterGraph, - "Filter Graph", - NULL, - "quartz.dll", - "Both" - }, - { &CLSID_FilterGraphNoThread, - "Filter Graph", - NULL, - "quartz.dll", - "Both" - }, - { &CLSID_FilterMapper, - "Filter Mapper", - NULL, - "quartz.dll", - "Both" - }, - { &CLSID_FilterMapper2, - "Filter Mapper2", - NULL, - "quartz.dll", - "Both" - }, - { &CLSID_SystemClock, - "System Clock", - NULL, - "quartz.dll", - "Both" - }, - { &CLSID_MemoryAllocator, - "Memory Allocator", - NULL, - "quartz.dll", - "Both" - }, - { &CLSID_SeekingPassThru, - "Seeking", - NULL, - "quartz.dll", - "Both" - }, - { &CLSID_AsyncReader, - "File Source Filter", - NULL, - "quartz.dll", - "Both" - }, - { &CLSID_AviSplitter, - "AVI Splitter", - NULL, - "quartz.dll", - "Both" - }, - { &CLSID_MPEG1Splitter, - "MPEG-I Stream Splitter", - NULL, - "quartz.dll", - "Both" - }, - { &CLSID_AVIDec, - "AVI Decompressor", - NULL, - "quartz.dll", - "Both" - }, - { &CLSID_DSoundRender, - "DirectSound Audio Renderer", - NULL, - "quartz.dll", - "Both" - }, - { &CLSID_AudioRender, - "Wave Audio Renderer", - NULL, - "quartz.dll", - "Both" - }, - { &CLSID_NullRenderer, - "Null Renderer", - NULL, - "quartz.dll", - "Both" - }, - { &CLSID_VideoRenderer, - "Video Renderer", - NULL, - "quartz.dll", - "Both" - }, - { &CLSID_VideoRendererDefault, - "Default Video Renderer", - NULL, - "quartz.dll", - "Both" - }, - { &CLSID_ACMWrapper, - "ACM wrapper", - NULL, - "quartz.dll", - "Both" - }, - { &CLSID_WAVEParser, - "Wave Parser", - NULL, - "quartz.dll", - "Both" - }, { NULL } /* list terminator */ }; @@ -997,7 +886,7 @@ static struct regsvr_filter const filter_list[] = { { &CLSID_AviSplitter, &CLSID_LegacyAmFilterCategory, {'A','V','I',' ','S','p','l','i','t','t','e','r',0}, - 0x600000, + 0x5ffff0, { { 0, { { &MEDIATYPE_Stream, &MEDIASUBTYPE_Avi }, { NULL } @@ -1014,7 +903,7 @@ static struct regsvr_filter const filter_list[] = { { &CLSID_MPEG1Splitter, &CLSID_LegacyAmFilterCategory, {'M','P','E','G','-','I',' ','S','t','r','e','a','m',' ','S','p','l','i','t','t','e','r',0}, - 0x600000, + 0x5ffff0, { { 0, { { &MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1Audio }, { &MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1Video }, @@ -1074,6 +963,18 @@ static struct regsvr_filter const filter_list[] = { { 0xFFFFFFFF }, } }, + { &CLSID_VideoMixingRenderer9, + &CLSID_LegacyAmFilterCategory, + {'V','i','d','e','o',' ','M','i','x','i','n','g',' ','R','e','n','d','e','r','e','r',' ','9',0}, + 0x200000, + { { REG_PINFLAG_B_RENDERER, + { { &MEDIATYPE_Video, &GUID_NULL }, + { NULL } + }, + }, + { 0xFFFFFFFF }, + } + }, { &CLSID_DSoundRender, &CLSID_LegacyAmFilterCategory, {'A','u','d','i','o',' ','R','e','n','d','e','r','e','r',0}, @@ -1103,7 +1004,7 @@ static struct regsvr_filter const filter_list[] = { { &CLSID_AVIDec, &CLSID_LegacyAmFilterCategory, {'A','V','I',' ','D','e','c','o','m','p','r','e','s','s','o','r',0}, - 0x600000, + 0x5ffff0, { { 0, { { &MEDIATYPE_Video, &GUID_NULL }, { NULL } @@ -1132,7 +1033,7 @@ static struct regsvr_filter const filter_list[] = { { &CLSID_ACMWrapper, &CLSID_LegacyAmFilterCategory, {'A','C','M',' ','W','r','a','p','p','e','r',0}, - 0x600000, + 0x5ffff0, { { 0, { { &MEDIATYPE_Audio, &GUID_NULL }, { NULL } diff --git a/reactos/dll/directx/quartz/systemclock.c b/reactos/dll/directx/quartz/systemclock.c index a36512e5f56..259c547fccc 100644 --- a/reactos/dll/directx/quartz/systemclock.c +++ b/reactos/dll/directx/quartz/systemclock.c @@ -37,7 +37,7 @@ struct SystemClockAdviseEntry { }; typedef struct SystemClockImpl { - const IReferenceClockVtbl *lpVtbl; + IReferenceClock IReferenceClock_iface; LONG ref; /** IReferenceClock */ @@ -52,6 +52,11 @@ typedef struct SystemClockImpl { SystemClockAdviseEntry* pPeriodicAdvise; } SystemClockImpl; +static inline SystemClockImpl *impl_from_IReferenceClock(IReferenceClock *iface) +{ + return CONTAINING_RECORD(iface, SystemClockImpl, IReferenceClock_iface); +} + static void QUARTZ_RemoveAviseEntryFromQueue(SystemClockImpl* This, SystemClockAdviseEntry* pEntry) { if (pEntry->prev) pEntry->prev->next = pEntry->next; @@ -104,19 +109,22 @@ static DWORD WINAPI SystemClockAdviseThread(LPVOID lpParam) { EnterCriticalSection(&This->safe); /*timeOut = IReferenceClock_OnTimerUpdated(This); */ - hr = IReferenceClock_GetTime((IReferenceClock*) This, &curTime); + hr = IReferenceClock_GetTime(&This->IReferenceClock_iface, &curTime); if (FAILED(hr)) { timeOut = INFINITE; goto outrefresh; } /** First SingleShots Advice: sorted list */ - for (it = This->pSingleShotAdvise; NULL != it && (it->rtBaseTime + it->rtIntervalTime) <= curTime; it = it->next) { + it = This->pSingleShotAdvise; + while ((NULL != it) && (it->rtBaseTime + it->rtIntervalTime) <= curTime) { + SystemClockAdviseEntry* nextit = it->next; /** send event ... */ SetEvent(it->hEvent); /** ... and Release it */ QUARTZ_RemoveAviseEntryFromQueue(This, it); CoTaskMemFree(it); + it = nextit; } if (NULL != it) timeOut = (DWORD) ((it->rtBaseTime + it->rtIntervalTime) - curTime) / (REFERENCE_TIME)10000; @@ -137,11 +145,11 @@ static DWORD WINAPI SystemClockAdviseThread(LPVOID lpParam) { outrefresh: LeaveCriticalSection(&This->safe); - while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) { + while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) { /** if hwnd we suppose that is a windows event ... */ if (NULL != msg.hwnd) { TranslateMessage(&msg); - DispatchMessageA(&msg); + DispatchMessageW(&msg); } else { switch (msg.message) { case WM_QUIT: @@ -178,7 +186,7 @@ static BOOL SystemClockPostMessageToAdviseThread(SystemClockImpl* This, UINT iMs SetThreadPriority(This->adviseThread, THREAD_PRIORITY_TIME_CRITICAL); This->adviseThreadActive = TRUE; while(1) { - res = PostThreadMessageA(This->adviseThreadId, iMsg, 0, 0); + res = PostThreadMessageW(This->adviseThreadId, iMsg, 0, 0); /* Let the thread creates its message queue (with MsgWaitForMultipleObjects call) by yielding and retrying */ if (!res && (GetLastError() == ERROR_INVALID_THREAD_ID)) Sleep(0); @@ -187,11 +195,11 @@ static BOOL SystemClockPostMessageToAdviseThread(SystemClockImpl* This, UINT iMs } return res; } - return PostThreadMessageA(This->adviseThreadId, iMsg, 0, 0); + return PostThreadMessageW(This->adviseThreadId, iMsg, 0, 0); } static ULONG WINAPI SystemClockImpl_AddRef(IReferenceClock* iface) { - SystemClockImpl *This = (SystemClockImpl *)iface; + SystemClockImpl *This = impl_from_IReferenceClock(iface); ULONG ref = InterlockedIncrement(&This->ref); TRACE("(%p): AddRef from %d\n", This, ref - 1); @@ -200,7 +208,7 @@ static ULONG WINAPI SystemClockImpl_AddRef(IReferenceClock* iface) { } static HRESULT WINAPI SystemClockImpl_QueryInterface(IReferenceClock* iface, REFIID riid, void** ppobj) { - SystemClockImpl *This = (SystemClockImpl *)iface; + SystemClockImpl *This = impl_from_IReferenceClock(iface); TRACE("(%p, %s,%p)\n", This, debugstr_guid(riid), ppobj); if (IsEqualIID (riid, &IID_IUnknown) || @@ -216,7 +224,7 @@ static HRESULT WINAPI SystemClockImpl_QueryInterface(IReferenceClock* iface, REF } static ULONG WINAPI SystemClockImpl_Release(IReferenceClock* iface) { - SystemClockImpl *This = (SystemClockImpl *)iface; + SystemClockImpl *This = impl_from_IReferenceClock(iface); ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p): ReleaseRef to %d\n", This, ref); if (ref == 0) { @@ -232,7 +240,7 @@ static ULONG WINAPI SystemClockImpl_Release(IReferenceClock* iface) { } static HRESULT WINAPI SystemClockImpl_GetTime(IReferenceClock* iface, REFERENCE_TIME* pTime) { - SystemClockImpl *This = (SystemClockImpl *)iface; + SystemClockImpl *This = impl_from_IReferenceClock(iface); DWORD curTimeTickCount; HRESULT hr = S_OK; @@ -254,7 +262,7 @@ static HRESULT WINAPI SystemClockImpl_GetTime(IReferenceClock* iface, REFERENCE_ } static HRESULT WINAPI SystemClockImpl_AdviseTime(IReferenceClock* iface, REFERENCE_TIME rtBaseTime, REFERENCE_TIME rtStreamTime, HEVENT hEvent, DWORD_PTR* pdwAdviseCookie) { - SystemClockImpl *This = (SystemClockImpl *)iface; + SystemClockImpl *This = impl_from_IReferenceClock(iface); SystemClockAdviseEntry* pEntry = NULL; TRACE("(%p, 0x%s, 0x%s, %ld, %p)\n", This, wine_dbgstr_longlong(rtBaseTime), @@ -290,7 +298,7 @@ static HRESULT WINAPI SystemClockImpl_AdviseTime(IReferenceClock* iface, REFEREN } static HRESULT WINAPI SystemClockImpl_AdvisePeriodic(IReferenceClock* iface, REFERENCE_TIME rtStartTime, REFERENCE_TIME rtPeriodTime, HSEMAPHORE hSemaphore, DWORD_PTR* pdwAdviseCookie) { - SystemClockImpl *This = (SystemClockImpl *)iface; + SystemClockImpl *This = impl_from_IReferenceClock(iface); SystemClockAdviseEntry* pEntry = NULL; TRACE("(%p, 0x%s, 0x%s, %ld, %p)\n", This, wine_dbgstr_longlong(rtStartTime), @@ -326,7 +334,7 @@ static HRESULT WINAPI SystemClockImpl_AdvisePeriodic(IReferenceClock* iface, REF } static HRESULT WINAPI SystemClockImpl_Unadvise(IReferenceClock* iface, DWORD_PTR dwAdviseCookie) { - SystemClockImpl *This = (SystemClockImpl *)iface; + SystemClockImpl *This = impl_from_IReferenceClock(iface); SystemClockAdviseEntry* pEntry = NULL; SystemClockAdviseEntry* it = NULL; HRESULT ret = S_OK; @@ -377,12 +385,12 @@ HRESULT QUARTZ_CreateSystemClock(IUnknown * pUnkOuter, LPVOID * ppv) { } ZeroMemory(obj, sizeof(SystemClockImpl)); - obj->lpVtbl = &SystemClock_Vtbl; + obj->IReferenceClock_iface.lpVtbl = &SystemClock_Vtbl; obj->ref = 0; /* will be inited by QueryInterface */ obj->lastTimeTickCount = GetTickCount(); InitializeCriticalSection(&obj->safe); obj->safe.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SystemClockImpl.safe"); - return SystemClockImpl_QueryInterface((IReferenceClock*) obj, &IID_IReferenceClock, ppv); + return SystemClockImpl_QueryInterface(&obj->IReferenceClock_iface, &IID_IReferenceClock, ppv); } diff --git a/reactos/dll/directx/quartz/transform.c b/reactos/dll/directx/quartz/transform.c deleted file mode 100644 index ceb04c171ed..00000000000 --- a/reactos/dll/directx/quartz/transform.c +++ /dev/null @@ -1,651 +0,0 @@ -/* - * Transform Filter (Base for decoders, etc...) - * - * Copyright 2005 Christian Costa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include - -#include "quartz_private.h" -//#include "control_private.h" -#include "pin.h" - -//#include "amvideo.h" -//#include "windef.h" -//#include "winbase.h" -//#include "dshow.h" -//#include "strmif.h" -//#include "vfw.h" - -//#include - -#include -#include - -#include "transform.h" - -WINE_DEFAULT_DEBUG_CHANNEL(quartz); - -static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0}; -static const WCHAR wcsOutputPinName[] = {'o','u','t','p','u','t',' ','p','i','n',0}; - -static const IBaseFilterVtbl TransformFilter_Vtbl; -static const IPinVtbl TransformFilter_InputPin_Vtbl; -static const IPinVtbl TransformFilter_OutputPin_Vtbl; - -static HRESULT TransformFilter_Input_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt) -{ - TransformFilterImpl* This = (TransformFilterImpl *)((IPinImpl *)iface)->pinInfo.pFilter; - TRACE("%p\n", iface); - dump_AM_MEDIA_TYPE(pmt); - - if (This->pFuncsTable->pfnQueryConnect) - return This->pFuncsTable->pfnQueryConnect(This, pmt); - /* Assume OK if there's no query method (the connection will fail if - needed) */ - return S_OK; -} - - -static HRESULT TransformFilter_Output_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt) -{ - TransformFilterImpl* pTransformFilter = iface; - AM_MEDIA_TYPE* outpmt = &pTransformFilter->pmt; - TRACE("%p\n", iface); - - if (IsEqualIID(&pmt->majortype, &outpmt->majortype) - && (IsEqualIID(&pmt->subtype, &outpmt->subtype) || IsEqualIID(&outpmt->subtype, &GUID_NULL))) - return S_OK; - return S_FALSE; -} - - -static inline TransformFilterImpl *impl_from_IMediaSeeking( IMediaSeeking *iface ) -{ - return (TransformFilterImpl *)((char*)iface - FIELD_OFFSET(TransformFilterImpl, mediaSeeking.lpVtbl)); -} - -static HRESULT WINAPI TransformFilter_Seeking_QueryInterface(IMediaSeeking * iface, REFIID riid, LPVOID * ppv) -{ - TransformFilterImpl *This = impl_from_IMediaSeeking(iface); - - return IUnknown_QueryInterface((IUnknown *)This, riid, ppv); -} - -static ULONG WINAPI TransformFilter_Seeking_AddRef(IMediaSeeking * iface) -{ - TransformFilterImpl *This = impl_from_IMediaSeeking(iface); - - return IUnknown_AddRef((IUnknown *)This); -} - -static ULONG WINAPI TransformFilter_Seeking_Release(IMediaSeeking * iface) -{ - TransformFilterImpl *This = impl_from_IMediaSeeking(iface); - - return IUnknown_Release((IUnknown *)This); -} - -static const IMediaSeekingVtbl TransformFilter_Seeking_Vtbl = -{ - TransformFilter_Seeking_QueryInterface, - TransformFilter_Seeking_AddRef, - TransformFilter_Seeking_Release, - MediaSeekingImpl_GetCapabilities, - MediaSeekingImpl_CheckCapabilities, - MediaSeekingImpl_IsFormatSupported, - MediaSeekingImpl_QueryPreferredFormat, - MediaSeekingImpl_GetTimeFormat, - MediaSeekingImpl_IsUsingTimeFormat, - MediaSeekingImpl_SetTimeFormat, - MediaSeekingImpl_GetDuration, - MediaSeekingImpl_GetStopPosition, - MediaSeekingImpl_GetCurrentPosition, - MediaSeekingImpl_ConvertTimeFormat, - MediaSeekingImpl_SetPositions, - MediaSeekingImpl_GetPositions, - MediaSeekingImpl_GetAvailable, - MediaSeekingImpl_SetRate, - MediaSeekingImpl_GetRate, - MediaSeekingImpl_GetPreroll -}; - -/* These shouldn't be implemented by default. - * Usually only source filters should implement these - * and even it's not needed all of the time - */ -static HRESULT TransformFilter_ChangeCurrent(IBaseFilter *iface) -{ - TRACE("(%p) filter hasn't implemented current position change!\n", iface); - return S_OK; -} - -static HRESULT TransformFilter_ChangeStop(IBaseFilter *iface) -{ - TRACE("(%p) filter hasn't implemented stop position change!\n", iface); - return S_OK; -} - -static HRESULT TransformFilter_ChangeRate(IBaseFilter *iface) -{ - TRACE("(%p) filter hasn't implemented rate change!\n", iface); - return S_OK; -} - -HRESULT TransformFilter_Create(TransformFilterImpl* pTransformFilter, const CLSID* pClsid, const TransformFuncsTable* pFuncsTable, CHANGEPROC stop, CHANGEPROC current, CHANGEPROC rate) -{ - HRESULT hr; - PIN_INFO piInput; - PIN_INFO piOutput; - - /* pTransformFilter is already allocated */ - pTransformFilter->clsid = *pClsid; - pTransformFilter->pFuncsTable = pFuncsTable; - - pTransformFilter->lpVtbl = &TransformFilter_Vtbl; - - pTransformFilter->refCount = 1; - InitializeCriticalSection(&pTransformFilter->csFilter); - pTransformFilter->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": TransformFilterImpl.csFilter"); - pTransformFilter->state = State_Stopped; - pTransformFilter->pClock = NULL; - ZeroMemory(&pTransformFilter->filterInfo, sizeof(FILTER_INFO)); - ZeroMemory(&pTransformFilter->pmt, sizeof(pTransformFilter->pmt)); - pTransformFilter->npins = 2; - - pTransformFilter->ppPins = CoTaskMemAlloc(2 * sizeof(IPin *)); - - /* construct input pin */ - piInput.dir = PINDIR_INPUT; - piInput.pFilter = (IBaseFilter *)pTransformFilter; - lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0])); - piOutput.dir = PINDIR_OUTPUT; - piOutput.pFilter = (IBaseFilter *)pTransformFilter; - lstrcpynW(piOutput.achName, wcsOutputPinName, sizeof(piOutput.achName) / sizeof(piOutput.achName[0])); - - hr = InputPin_Construct(&TransformFilter_InputPin_Vtbl, &piInput, (SAMPLEPROC_PUSH)pFuncsTable->pfnProcessSampleData, NULL, TransformFilter_Input_QueryAccept, NULL, &pTransformFilter->csFilter, NULL, &pTransformFilter->ppPins[0]); - - if (SUCCEEDED(hr)) - { - ALLOCATOR_PROPERTIES props; - props.cbAlign = 1; - props.cbPrefix = 0; - props.cbBuffer = 0; /* Will be updated at connection time */ - props.cBuffers = 1; - - ((InputPin *)pTransformFilter->ppPins[0])->pin.pUserData = pTransformFilter->ppPins[0]; - - hr = OutputPin_Construct(&TransformFilter_OutputPin_Vtbl, sizeof(OutputPin), &piOutput, &props, pTransformFilter, TransformFilter_Output_QueryAccept, &pTransformFilter->csFilter, &pTransformFilter->ppPins[1]); - - if (FAILED(hr)) - ERR("Cannot create output pin (%x)\n", hr); - else - { - if (!stop) - stop = TransformFilter_ChangeStop; - if (!current) - current = TransformFilter_ChangeCurrent; - if (!rate) - rate = TransformFilter_ChangeRate; - - MediaSeekingImpl_Init((IBaseFilter*)pTransformFilter, stop, current, rate, &pTransformFilter->mediaSeeking, &pTransformFilter->csFilter); - pTransformFilter->mediaSeeking.lpVtbl = &TransformFilter_Seeking_Vtbl; - } - } - else - { - CoTaskMemFree(pTransformFilter->ppPins); - pTransformFilter->csFilter.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&pTransformFilter->csFilter); - CoTaskMemFree(pTransformFilter); - } - - return hr; -} - -static HRESULT WINAPI TransformFilter_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv) -{ - TransformFilterImpl *This = (TransformFilterImpl *)iface; - TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv); - - *ppv = NULL; - - if (IsEqualIID(riid, &IID_IUnknown)) - *ppv = This; - else if (IsEqualIID(riid, &IID_IPersist)) - *ppv = This; - else if (IsEqualIID(riid, &IID_IMediaFilter)) - *ppv = This; - else if (IsEqualIID(riid, &IID_IBaseFilter)) - *ppv = This; - else if (IsEqualIID(riid, &IID_IMediaSeeking)) - *ppv = &This->mediaSeeking; - - if (*ppv) - { - IUnknown_AddRef((IUnknown *)(*ppv)); - return S_OK; - } - - if (!IsEqualIID(riid, &IID_IPin) && !IsEqualIID(riid, &IID_IVideoWindow)) - FIXME("No interface for %s!\n", qzdebugstr_guid(riid)); - - return E_NOINTERFACE; -} - -static ULONG WINAPI TransformFilter_AddRef(IBaseFilter * iface) -{ - TransformFilterImpl *This = (TransformFilterImpl *)iface; - ULONG refCount = InterlockedIncrement(&This->refCount); - - TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1); - - return refCount; -} - -static ULONG WINAPI TransformFilter_Release(IBaseFilter * iface) -{ - TransformFilterImpl *This = (TransformFilterImpl *)iface; - ULONG refCount = InterlockedDecrement(&This->refCount); - - TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1); - - if (!refCount) - { - ULONG i; - - if (This->pClock) - IReferenceClock_Release(This->pClock); - - for (i = 0; i < This->npins; i++) - { - IPin *pConnectedTo; - - if (SUCCEEDED(IPin_ConnectedTo(This->ppPins[i], &pConnectedTo))) - { - IPin_Disconnect(pConnectedTo); - IPin_Release(pConnectedTo); - } - IPin_Disconnect(This->ppPins[i]); - - IPin_Release(This->ppPins[i]); - } - - CoTaskMemFree(This->ppPins); - This->lpVtbl = NULL; - - This->csFilter.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&This->csFilter); - - TRACE("Destroying transform filter\n"); - FreeMediaType(&This->pmt); - CoTaskMemFree(This); - - return 0; - } - else - return refCount; -} - -/** IPersist methods **/ - -static HRESULT WINAPI TransformFilter_GetClassID(IBaseFilter * iface, CLSID * pClsid) -{ - TransformFilterImpl *This = (TransformFilterImpl *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, pClsid); - - *pClsid = This->clsid; - - return S_OK; -} - -/** IMediaFilter methods **/ - -static HRESULT WINAPI TransformFilter_Stop(IBaseFilter * iface) -{ - TransformFilterImpl *This = (TransformFilterImpl *)iface; - HRESULT hr = S_OK; - - TRACE("(%p/%p)\n", This, iface); - - EnterCriticalSection(&This->csFilter); - { - This->state = State_Stopped; - if (This->pFuncsTable->pfnProcessEnd) - hr = This->pFuncsTable->pfnProcessEnd(This); - } - LeaveCriticalSection(&This->csFilter); - - return hr; -} - -static HRESULT WINAPI TransformFilter_Pause(IBaseFilter * iface) -{ - TransformFilterImpl *This = (TransformFilterImpl *)iface; - HRESULT hr; - - TRACE("(%p/%p)->()\n", This, iface); - - EnterCriticalSection(&This->csFilter); - { - if (This->state == State_Stopped) - hr = IBaseFilter_Run(iface, -1); - else - hr = S_OK; - - if (SUCCEEDED(hr)) - This->state = State_Paused; - } - LeaveCriticalSection(&This->csFilter); - - return hr; -} - -static HRESULT WINAPI TransformFilter_Run(IBaseFilter * iface, REFERENCE_TIME tStart) -{ - HRESULT hr = S_OK; - TransformFilterImpl *This = (TransformFilterImpl *)iface; - - TRACE("(%p/%p)->(%s)\n", This, iface, wine_dbgstr_longlong(tStart)); - - EnterCriticalSection(&This->csFilter); - { - if (This->state == State_Stopped) - { - ((InputPin *)This->ppPins[0])->end_of_stream = 0; - if (This->pFuncsTable->pfnProcessBegin) - hr = This->pFuncsTable->pfnProcessBegin(This); - if (SUCCEEDED(hr)) - hr = OutputPin_CommitAllocator((OutputPin *)This->ppPins[1]); - } - - if (SUCCEEDED(hr)) - { - This->rtStreamStart = tStart; - This->state = State_Running; - } - } - LeaveCriticalSection(&This->csFilter); - - return hr; -} - -static HRESULT WINAPI TransformFilter_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState) -{ - TransformFilterImpl *This = (TransformFilterImpl *)iface; - - TRACE("(%p/%p)->(%d, %p)\n", This, iface, dwMilliSecsTimeout, pState); - - EnterCriticalSection(&This->csFilter); - { - *pState = This->state; - } - LeaveCriticalSection(&This->csFilter); - - return S_OK; -} - -static HRESULT WINAPI TransformFilter_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock) -{ - TransformFilterImpl *This = (TransformFilterImpl *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, pClock); - - EnterCriticalSection(&This->csFilter); - { - if (This->pClock) - IReferenceClock_Release(This->pClock); - This->pClock = pClock; - if (This->pClock) - IReferenceClock_AddRef(This->pClock); - } - LeaveCriticalSection(&This->csFilter); - - return S_OK; -} - -static HRESULT WINAPI TransformFilter_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock) -{ - TransformFilterImpl *This = (TransformFilterImpl *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, ppClock); - - EnterCriticalSection(&This->csFilter); - { - *ppClock = This->pClock; - if (This->pClock) - IReferenceClock_AddRef(This->pClock); - } - LeaveCriticalSection(&This->csFilter); - - return S_OK; -} - -/** IBaseFilter implementation **/ - -static HRESULT TransformFilter_GetPin(IBaseFilter *iface, ULONG pos, IPin **pin, DWORD *lastsynctick) -{ - TransformFilterImpl *This = (TransformFilterImpl *)iface; - - /* Our pins are static, not changing so setting static tick count is ok */ - *lastsynctick = 0; - - if (pos >= This->npins) - return S_FALSE; - - *pin = This->ppPins[pos]; - IPin_AddRef(*pin); - return S_OK; -} - -static HRESULT WINAPI TransformFilter_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum) -{ - TransformFilterImpl *This = (TransformFilterImpl *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum); - - return IEnumPinsImpl_Construct(ppEnum, TransformFilter_GetPin, iface); -} - -static HRESULT WINAPI TransformFilter_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin) -{ - TransformFilterImpl *This = (TransformFilterImpl *)iface; - - TRACE("(%p/%p)->(%p,%p)\n", This, iface, debugstr_w(Id), ppPin); - - return E_NOTIMPL; -} - -static HRESULT WINAPI TransformFilter_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo) -{ - TransformFilterImpl *This = (TransformFilterImpl *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, pInfo); - - strcpyW(pInfo->achName, This->filterInfo.achName); - pInfo->pGraph = This->filterInfo.pGraph; - - if (pInfo->pGraph) - IFilterGraph_AddRef(pInfo->pGraph); - - return S_OK; -} - -static HRESULT WINAPI TransformFilter_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName) -{ - HRESULT hr = S_OK; - TransformFilterImpl *This = (TransformFilterImpl *)iface; - - TRACE("(%p/%p)->(%p, %s)\n", This, iface, pGraph, debugstr_w(pName)); - - EnterCriticalSection(&This->csFilter); - { - if (pName) - strcpyW(This->filterInfo.achName, pName); - else - *This->filterInfo.achName = '\0'; - This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */ - } - LeaveCriticalSection(&This->csFilter); - - return hr; -} - -static HRESULT WINAPI TransformFilter_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo) -{ - TransformFilterImpl *This = (TransformFilterImpl *)iface; - TRACE("(%p/%p)->(%p)\n", This, iface, pVendorInfo); - return E_NOTIMPL; -} - -static const IBaseFilterVtbl TransformFilter_Vtbl = -{ - TransformFilter_QueryInterface, - TransformFilter_AddRef, - TransformFilter_Release, - TransformFilter_GetClassID, - TransformFilter_Stop, - TransformFilter_Pause, - TransformFilter_Run, - TransformFilter_GetState, - TransformFilter_SetSyncSource, - TransformFilter_GetSyncSource, - TransformFilter_EnumPins, - TransformFilter_FindPin, - TransformFilter_QueryFilterInfo, - TransformFilter_JoinFilterGraph, - TransformFilter_QueryVendorInfo -}; - -static HRESULT WINAPI TransformFilter_InputPin_EndOfStream(IPin * iface) -{ - InputPin* This = (InputPin*) iface; - TransformFilterImpl* pTransform; - IPin* ppin; - HRESULT hr; - - TRACE("(%p)->()\n", iface); - - /* Since we process samples synchronously, just forward notification downstream */ - pTransform = (TransformFilterImpl*)This->pin.pinInfo.pFilter; - if (!pTransform) - hr = E_FAIL; - else - hr = IPin_ConnectedTo(pTransform->ppPins[1], &ppin); - if (SUCCEEDED(hr)) - { - hr = IPin_EndOfStream(ppin); - IPin_Release(ppin); - } - - if (FAILED(hr)) - ERR("%x\n", hr); - return hr; -} - -static HRESULT WINAPI TransformFilter_InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) -{ - InputPin* This = (InputPin*) iface; - TransformFilterImpl* pTransform; - HRESULT hr; - - TRACE("(%p)->(%p, %p)\n", iface, pReceivePin, pmt); - - pTransform = (TransformFilterImpl*)This->pin.pinInfo.pFilter; - - hr = pTransform->pFuncsTable->pfnConnectInput(This, pmt); - if (SUCCEEDED(hr)) - { - hr = InputPin_ReceiveConnection(iface, pReceivePin, pmt); - if (FAILED(hr)) - pTransform->pFuncsTable->pfnCleanup(This); - } - - return hr; -} - -static HRESULT WINAPI TransformFilter_InputPin_Disconnect(IPin * iface) -{ - InputPin* This = (InputPin*) iface; - TransformFilterImpl* pTransform; - - TRACE("(%p)->()\n", iface); - - pTransform = (TransformFilterImpl*)This->pin.pinInfo.pFilter; - pTransform->pFuncsTable->pfnCleanup(This); - - return IPinImpl_Disconnect(iface); -} - -static const IPinVtbl TransformFilter_InputPin_Vtbl = -{ - InputPin_QueryInterface, - IPinImpl_AddRef, - InputPin_Release, - InputPin_Connect, - TransformFilter_InputPin_ReceiveConnection, - TransformFilter_InputPin_Disconnect, - IPinImpl_ConnectedTo, - IPinImpl_ConnectionMediaType, - IPinImpl_QueryPinInfo, - IPinImpl_QueryDirection, - IPinImpl_QueryId, - IPinImpl_QueryAccept, - IPinImpl_EnumMediaTypes, - IPinImpl_QueryInternalConnections, - TransformFilter_InputPin_EndOfStream, - InputPin_BeginFlush, - InputPin_EndFlush, - InputPin_NewSegment -}; - -static HRESULT WINAPI TransformFilter_Output_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum) -{ - IPinImpl *This = (IPinImpl *)iface; - TransformFilterImpl *pTransform = (TransformFilterImpl *)This->pinInfo.pFilter; - ENUMMEDIADETAILS emd; - - TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum); - - emd.cMediaTypes = 1; - emd.pMediaTypes = &pTransform->pmt; - - return IEnumMediaTypesImpl_Construct(&emd, ppEnum); -} - -static const IPinVtbl TransformFilter_OutputPin_Vtbl = -{ - OutputPin_QueryInterface, - IPinImpl_AddRef, - OutputPin_Release, - OutputPin_Connect, - OutputPin_ReceiveConnection, - OutputPin_Disconnect, - IPinImpl_ConnectedTo, - IPinImpl_ConnectionMediaType, - IPinImpl_QueryPinInfo, - IPinImpl_QueryDirection, - IPinImpl_QueryId, - IPinImpl_QueryAccept, - TransformFilter_Output_EnumMediaTypes, - IPinImpl_QueryInternalConnections, - OutputPin_EndOfStream, - OutputPin_BeginFlush, - OutputPin_EndFlush, - OutputPin_NewSegment -}; diff --git a/reactos/dll/directx/quartz/transform.h b/reactos/dll/directx/quartz/transform.h deleted file mode 100644 index f39ff47846b..00000000000 --- a/reactos/dll/directx/quartz/transform.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Transform Filter declarations - * - * Copyright 2005 Christian Costa - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include "control_private.h" - -typedef struct TransformFilterImpl TransformFilterImpl; - -typedef struct TransformFuncsTable { - HRESULT (*pfnProcessBegin) (TransformFilterImpl *This); - HRESULT (*pfnProcessSampleData) (InputPin *pin, IMediaSample *pSample); - HRESULT (*pfnProcessEnd) (TransformFilterImpl *This); - HRESULT (*pfnQueryConnect) (TransformFilterImpl *This, const AM_MEDIA_TYPE * pmt); - HRESULT (*pfnConnectInput) (InputPin *pin, const AM_MEDIA_TYPE * pmt); - HRESULT (*pfnCleanup) (InputPin *pin); -} TransformFuncsTable; - -struct TransformFilterImpl -{ - const IBaseFilterVtbl * lpVtbl; - - LONG refCount; - CRITICAL_SECTION csFilter; - FILTER_STATE state; - REFERENCE_TIME rtStreamStart; - IReferenceClock * pClock; - FILTER_INFO filterInfo; - CLSID clsid; - struct MediaSeekingImpl mediaSeeking; - - IPin **ppPins; - ULONG npins; - AM_MEDIA_TYPE pmt; - - const TransformFuncsTable * pFuncsTable; -}; - -HRESULT TransformFilter_Create(TransformFilterImpl*, const CLSID*, const TransformFuncsTable* pFuncsTable, CHANGEPROC stop, CHANGEPROC current, CHANGEPROC rate); diff --git a/reactos/dll/directx/quartz/version.rc b/reactos/dll/directx/quartz/version.rc index 930039df3fc..a44475bc723 100644 --- a/reactos/dll/directx/quartz/version.rc +++ b/reactos/dll/directx/quartz/version.rc @@ -16,12 +16,17 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#define WINE_OLESELFREGISTER #define WINE_FILEDESCRIPTION_STR "Wine Quartz dll" #define WINE_FILENAME_STR "quartz.dll" #define WINE_FILEVERSION 6,5,1,902 #define WINE_FILEVERSION_STR "6.5.1.902" #define WINE_PRODUCTVERSION 6,5,1,902 #define WINE_PRODUCTVERSION_STR "6.5" +#define WINE_EXTRAVALUES VALUE "OLESelfRegister","" #include "wine/wine_common_ver.rc" + +1 TYPELIB control_tlb.tlb + +1 WINE_REGISTRY control_tlb.rgs +2 WINE_REGISTRY quartz_strmif.rgs diff --git a/reactos/dll/directx/quartz/videorenderer.c b/reactos/dll/directx/quartz/videorenderer.c index 17042a7e1e8..c29fbd30885 100644 --- a/reactos/dll/directx/quartz/videorenderer.c +++ b/reactos/dll/directx/quartz/videorenderer.c @@ -23,7 +23,6 @@ #define NONAMELESSSTRUCT #define NONAMELESSUNION #include "quartz_private.h" -#include "control_private.h" #include "pin.h" //#include "uuids.h" @@ -43,163 +42,58 @@ WINE_DEFAULT_DEBUG_CHANNEL(quartz); -static BOOL wnd_class_registered = FALSE; - -static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0}; - -static const IBaseFilterVtbl VideoRenderer_Vtbl; -static const IUnknownVtbl IInner_VTable; -static const IBasicVideoVtbl IBasicVideo_VTable; -static const IVideoWindowVtbl IVideoWindow_VTable; -static const IPinVtbl VideoRenderer_InputPin_Vtbl; - typedef struct VideoRendererImpl { - const IBaseFilterVtbl * lpVtbl; - const IBasicVideoVtbl * IBasicVideo_vtbl; - const IVideoWindowVtbl * IVideoWindow_vtbl; - const IUnknownVtbl * IInner_vtbl; + BaseRenderer renderer; + BaseControlWindow baseControlWindow; + BaseControlVideo baseControlVideo; - LONG refCount; - CRITICAL_SECTION csFilter; - FILTER_STATE state; - REFERENCE_TIME rtStreamStart; - IReferenceClock * pClock; - FILTER_INFO filterInfo; - - InputPin *pInputPin; + IUnknown IUnknown_inner; + IAMFilterMiscFlags IAMFilterMiscFlags_iface; + IUnknown *outer_unk; BOOL init; HANDLE hThread; - HANDLE blocked; DWORD ThreadID; HANDLE hEvent; +/* hEvent == evComplete? */ BOOL ThreadResult; - HWND hWnd; - HWND hWndMsgDrain; - BOOL AutoShow; RECT SourceRect; RECT DestRect; RECT WindowPos; LONG VideoWidth; LONG VideoHeight; - IUnknown * pUnkOuter; - BOOL bUnkOuterValid; - BOOL bAggregatable; - REFERENCE_TIME rtLastStop; - MediaSeekingImpl mediaSeeking; - - /* During pause we can hold a single sample, for use in GetCurrentImage */ - IMediaSample *sample_held; } VideoRendererImpl; -static LRESULT CALLBACK VideoWndProcA(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +static inline VideoRendererImpl *impl_from_BaseWindow(BaseWindow *iface) { - VideoRendererImpl* pVideoRenderer = (VideoRendererImpl*)GetWindowLongPtrW(hwnd, 0); - LPRECT lprect = (LPRECT)lParam; - - if (pVideoRenderer && pVideoRenderer->hWndMsgDrain) - { - switch(uMsg) - { - case WM_KEYDOWN: - case WM_KEYUP: - case WM_LBUTTONDBLCLK: - case WM_LBUTTONDOWN: - case WM_LBUTTONUP: - case WM_MBUTTONDBLCLK: - case WM_MBUTTONDOWN: - case WM_MBUTTONUP: - case WM_MOUSEACTIVATE: - case WM_MOUSEMOVE: - case WM_NCLBUTTONDBLCLK: - case WM_NCLBUTTONDOWN: - case WM_NCLBUTTONUP: - case WM_NCMBUTTONDBLCLK: - case WM_NCMBUTTONDOWN: - case WM_NCMBUTTONUP: - case WM_NCMOUSEMOVE: - case WM_NCRBUTTONDBLCLK: - case WM_NCRBUTTONDOWN: - case WM_NCRBUTTONUP: - case WM_RBUTTONDBLCLK: - case WM_RBUTTONDOWN: - case WM_RBUTTONUP: - PostMessageA(pVideoRenderer->hWndMsgDrain, uMsg, wParam, lParam); - break; - default: - break; - } - } - - switch(uMsg) - { - case WM_SIZING: - /* TRACE("WM_SIZING %d %d %d %d\n", lprect->left, lprect->top, lprect->right, lprect->bottom); */ - SetWindowPos(hwnd, NULL, lprect->left, lprect->top, lprect->right - lprect->left, lprect->bottom - lprect->top, SWP_NOZORDER); - GetClientRect(hwnd, &pVideoRenderer->DestRect); - TRACE("WM_SIZING: DestRect=(%d,%d),(%d,%d)\n", - pVideoRenderer->DestRect.left, - pVideoRenderer->DestRect.top, - pVideoRenderer->DestRect.right - pVideoRenderer->DestRect.left, - pVideoRenderer->DestRect.bottom - pVideoRenderer->DestRect.top); - return TRUE; - case WM_SIZE: - TRACE("WM_SIZE %d %d\n", LOWORD(lParam), HIWORD(lParam)); - GetClientRect(hwnd, &pVideoRenderer->DestRect); - TRACE("WM_SIZING: DestRect=(%d,%d),(%d,%d)\n", - pVideoRenderer->DestRect.left, - pVideoRenderer->DestRect.top, - pVideoRenderer->DestRect.right - pVideoRenderer->DestRect.left, - pVideoRenderer->DestRect.bottom - pVideoRenderer->DestRect.top); - return TRUE; - default: - return DefWindowProcA(hwnd, uMsg, wParam, lParam); - } - return 0; + return CONTAINING_RECORD(iface, VideoRendererImpl, baseControlWindow.baseWindow); } -static BOOL CreateRenderingWindow(VideoRendererImpl* This) +static inline VideoRendererImpl *impl_from_BaseRenderer(BaseRenderer *iface) { - WNDCLASSA winclass; + return CONTAINING_RECORD(iface, VideoRendererImpl, renderer); +} - TRACE("(%p)->()\n", This); - - winclass.style = 0; - winclass.lpfnWndProc = VideoWndProcA; - winclass.cbClsExtra = 0; - winclass.cbWndExtra = sizeof(VideoRendererImpl*); - winclass.hInstance = NULL; - winclass.hIcon = NULL; - winclass.hCursor = NULL; - winclass.hbrBackground = GetStockObject(BLACK_BRUSH); - winclass.lpszMenuName = NULL; - winclass.lpszClassName = "Wine ActiveMovie Class"; +static inline VideoRendererImpl *impl_from_IBaseFilter(IBaseFilter *iface) +{ + return CONTAINING_RECORD(iface, VideoRendererImpl, renderer.filter.IBaseFilter_iface); +} - if (!wnd_class_registered) - { - if (!RegisterClassA(&winclass)) - { - ERR("Unable to register window %u\n", GetLastError()); - return FALSE; - } - wnd_class_registered = TRUE; - } +static inline VideoRendererImpl *impl_from_IVideoWindow(IVideoWindow *iface) +{ + return CONTAINING_RECORD(iface, VideoRendererImpl, baseControlWindow.IVideoWindow_iface); +} - This->hWnd = CreateWindowExA(0, "Wine ActiveMovie Class", "Wine ActiveMovie Window", WS_SIZEBOX, - CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, - NULL, NULL, NULL); +static inline VideoRendererImpl *impl_from_BaseControlVideo(BaseControlVideo *iface) +{ + return CONTAINING_RECORD(iface, VideoRendererImpl, baseControlVideo); +} - if (!This->hWnd) - { - ERR("Unable to create window\n"); - return FALSE; - } - - SetWindowLongPtrW(This->hWnd, 0, (LONG_PTR)This); - - return TRUE; +static inline VideoRendererImpl *impl_from_IBasicVideo(IBasicVideo *iface) +{ + return CONTAINING_RECORD(iface, VideoRendererImpl, baseControlVideo.IBasicVideo_iface); } static DWORD WINAPI MessageLoop(LPVOID lpParameter) @@ -210,7 +104,7 @@ static DWORD WINAPI MessageLoop(LPVOID lpParameter) TRACE("Starting message loop\n"); - if (!CreateRenderingWindow(This)) + if (FAILED(BaseWindowImpl_PrepareWindow(&This->baseControlWindow.baseWindow))) { This->ThreadResult = FALSE; SetEvent(This->hEvent); @@ -220,10 +114,10 @@ static DWORD WINAPI MessageLoop(LPVOID lpParameter) This->ThreadResult = TRUE; SetEvent(This->hEvent); - while ((fGotMessage = GetMessageA(&msg, NULL, 0, 0)) != 0 && fGotMessage != -1) + while ((fGotMessage = GetMessageW(&msg, NULL, 0, 0)) != 0 && fGotMessage != -1) { TranslateMessage(&msg); - DispatchMessageA(&msg); + DispatchMessageW(&msg); } TRACE("End of message loop\n"); @@ -256,18 +150,68 @@ static BOOL CreateRenderingSubsystem(VideoRendererImpl* This) return TRUE; } +static void VideoRenderer_AutoShowWindow(VideoRendererImpl *This) +{ + if (!This->init && (!This->WindowPos.right || !This->WindowPos.top)) + { + DWORD style = GetWindowLongW(This->baseControlWindow.baseWindow.hWnd, GWL_STYLE); + DWORD style_ex = GetWindowLongW(This->baseControlWindow.baseWindow.hWnd, GWL_EXSTYLE); + + if (!This->WindowPos.right) + { + if (This->DestRect.right) + { + This->WindowPos.left = This->DestRect.left; + This->WindowPos.right = This->DestRect.right; + } + else + { + This->WindowPos.left = This->SourceRect.left; + This->WindowPos.right = This->SourceRect.right; + } + } + if (!This->WindowPos.bottom) + { + if (This->DestRect.bottom) + { + This->WindowPos.top = This->DestRect.top; + This->WindowPos.bottom = This->DestRect.bottom; + } + else + { + This->WindowPos.top = This->SourceRect.top; + This->WindowPos.bottom = This->SourceRect.bottom; + } + } + + AdjustWindowRectEx(&This->WindowPos, style, FALSE, style_ex); + + TRACE("WindowPos: %d %d %d %d\n", This->WindowPos.left, This->WindowPos.top, This->WindowPos.right, This->WindowPos.bottom); + SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL, + This->WindowPos.left, + This->WindowPos.top, + This->WindowPos.right - This->WindowPos.left, + This->WindowPos.bottom - This->WindowPos.top, + SWP_NOZORDER|SWP_NOMOVE|SWP_DEFERERASE); + + GetClientRect(This->baseControlWindow.baseWindow.hWnd, &This->DestRect); + } + else if (!This->init) + This->DestRect = This->WindowPos; + This->init = TRUE; + if (This->baseControlWindow.AutoShow) + ShowWindow(This->baseControlWindow.baseWindow.hWnd, SW_SHOW); +} + static DWORD VideoRenderer_SendSampleData(VideoRendererImpl* This, LPBYTE data, DWORD size) { AM_MEDIA_TYPE amt; HRESULT hr = S_OK; - DDSURFACEDESC sdesc; - HDC hDC; BITMAPINFOHEADER *bmiHeader; TRACE("(%p)->(%p, %d)\n", This, data, size); - sdesc.dwSize = sizeof(sdesc); - hr = IPin_ConnectionMediaType((IPin *)This->pInputPin, &amt); + hr = IPin_ConnectionMediaType(&This->renderer.pInputPin->pin.IPin_iface, &amt); if (FAILED(hr)) { ERR("Unable to retrieve media type\n"); return hr; @@ -295,31 +239,7 @@ static DWORD VideoRenderer_SendSampleData(VideoRendererImpl* This, LPBYTE data, TRACE("biCompression = %s\n", debugstr_an((LPSTR)&(bmiHeader->biCompression), 4)); TRACE("biSizeImage = %d\n", bmiHeader->biSizeImage); - if (!This->init) - { - DWORD style = GetWindowLongW(This->hWnd, GWL_STYLE); - DWORD style_ex = GetWindowLongW(This->hWnd, GWL_EXSTYLE); - - if (!This->WindowPos.right || !This->WindowPos.bottom) - This->WindowPos = This->SourceRect; - - AdjustWindowRectEx(&This->WindowPos, style, TRUE, style_ex); - - TRACE("WindowPos: %d %d %d %d\n", This->WindowPos.left, This->WindowPos.top, This->WindowPos.right, This->WindowPos.bottom); - SetWindowPos(This->hWnd, NULL, - This->WindowPos.left, - This->WindowPos.top, - This->WindowPos.right - This->WindowPos.left, - This->WindowPos.bottom - This->WindowPos.top, - SWP_NOZORDER|SWP_NOMOVE); - - GetClientRect(This->hWnd, &This->DestRect); - This->init = TRUE; - } - - hDC = GetDC(This->hWnd); - - if (!hDC) { + if (!This->baseControlWindow.baseWindow.hDC) { ERR("Cannot get DC from window!\n"); return E_FAIL; } @@ -327,69 +247,35 @@ static DWORD VideoRenderer_SendSampleData(VideoRendererImpl* This, LPBYTE data, TRACE("Src Rect: %d %d %d %d\n", This->SourceRect.left, This->SourceRect.top, This->SourceRect.right, This->SourceRect.bottom); TRACE("Dst Rect: %d %d %d %d\n", This->DestRect.left, This->DestRect.top, This->DestRect.right, This->DestRect.bottom); - StretchDIBits(hDC, This->DestRect.left, This->DestRect.top, This->DestRect.right -This->DestRect.left, + StretchDIBits(This->baseControlWindow.baseWindow.hDC, This->DestRect.left, This->DestRect.top, This->DestRect.right -This->DestRect.left, This->DestRect.bottom - This->DestRect.top, This->SourceRect.left, This->SourceRect.top, This->SourceRect.right - This->SourceRect.left, This->SourceRect.bottom - This->SourceRect.top, data, (BITMAPINFO *)bmiHeader, DIB_RGB_COLORS, SRCCOPY); - ReleaseDC(This->hWnd, hDC); - if (This->AutoShow) - ShowWindow(This->hWnd, SW_SHOW); - return S_OK; } -static HRESULT VideoRenderer_Sample(LPVOID iface, IMediaSample * pSample) +static HRESULT WINAPI VideoRenderer_ShouldDrawSampleNow(BaseRenderer *This, IMediaSample *pSample, REFERENCE_TIME *pStartTime, REFERENCE_TIME *pEndTime) { - VideoRendererImpl *This = iface; - LPBYTE pbSrcStream = NULL; - LONG cbSrcStream = 0; - REFERENCE_TIME tStart, tStop; - HRESULT hr; - - TRACE("(%p)->(%p)\n", iface, pSample); - - EnterCriticalSection(&This->csFilter); - - if (This->pInputPin->flushing || This->pInputPin->end_of_stream) - { - LeaveCriticalSection(&This->csFilter); - return S_FALSE; - } - - if (This->state == State_Stopped) - { - LeaveCriticalSection(&This->csFilter); - return VFW_E_WRONG_STATE; - } - - hr = IMediaSample_GetTime(pSample, &tStart, &tStop); - if (FAILED(hr)) - ERR("Cannot get sample time (%x)\n", hr); - - if (This->rtLastStop != tStart) - { - if (IMediaSample_IsDiscontinuity(pSample) == S_FALSE) - ERR("Unexpected discontinuity: Last: %u.%03u, tStart: %u.%03u\n", - (DWORD)(This->rtLastStop / 10000000), - (DWORD)((This->rtLastStop / 10000)%1000), - (DWORD)(tStart / 10000000), (DWORD)((tStart / 10000)%1000)); - This->rtLastStop = tStart; - } - /* Preroll means the sample isn't shown, this is used for key frames and things like that */ if (IMediaSample_IsPreroll(pSample) == S_OK) - { - This->rtLastStop = tStop; - LeaveCriticalSection(&This->csFilter); - return S_OK; - } + return E_FAIL; + return S_FALSE; +} + +static HRESULT WINAPI VideoRenderer_DoRenderSample(BaseRenderer* iface, IMediaSample * pSample) +{ + VideoRendererImpl *This = impl_from_BaseRenderer(iface); + LPBYTE pbSrcStream = NULL; + LONG cbSrcStream = 0; + HRESULT hr; + + TRACE("(%p)->(%p)\n", This, pSample); hr = IMediaSample_GetPointer(pSample, &pbSrcStream); if (FAILED(hr)) { ERR("Cannot get pointer to sample data (%x)\n", hr); - LeaveCriticalSection(&This->csFilter); return hr; } @@ -411,68 +297,29 @@ static HRESULT VideoRenderer_Sample(LPVOID iface, IMediaSample * pSample) #endif SetEvent(This->hEvent); - if (This->state == State_Paused) + if (This->renderer.filter.state == State_Paused) { - This->sample_held = pSample; - LeaveCriticalSection(&This->csFilter); - WaitForSingleObject(This->blocked, INFINITE); - EnterCriticalSection(&This->csFilter); - This->sample_held = NULL; - if (This->state == State_Paused) + VideoRenderer_SendSampleData(This, pbSrcStream, cbSrcStream); + SetEvent(This->hEvent); + if (This->renderer.filter.state == State_Paused) { /* Flushing */ - LeaveCriticalSection(&This->csFilter); return S_OK; } - if (This->state == State_Stopped) + if (This->renderer.filter.state == State_Stopped) { - LeaveCriticalSection(&This->csFilter); return VFW_E_WRONG_STATE; } + } else { + VideoRenderer_SendSampleData(This, pbSrcStream, cbSrcStream); } - - if (This->pClock && This->state == State_Running) - { - REFERENCE_TIME time, trefstart, trefstop; - LONG delta; - - /* Perhaps I use the reference clock AdviseTime function here - * I'm not going to! When I tried, it seemed to generate lag and - * it caused instability. - */ - IReferenceClock_GetTime(This->pClock, &time); - - trefstart = This->rtStreamStart; - trefstop = (REFERENCE_TIME)((double)(tStop - tStart) / This->pInputPin->dRate) + This->rtStreamStart; - delta = (LONG)((trefstart-time)/10000); - This->rtStreamStart = trefstop; - This->rtLastStop = tStop; - - if (delta > 0) - { - TRACE("Sleeping for %u ms\n", delta); - Sleep(delta); - } - else if (time > trefstop) - { - TRACE("Dropping sample: Time: %u.%03u ms trefstop: %u.%03u ms!\n", - (DWORD)(time / 10000000), (DWORD)((time / 10000)%1000), - (DWORD)(trefstop / 10000000), (DWORD)((trefstop / 10000)%1000) ); - This->rtLastStop = tStop; - LeaveCriticalSection(&This->csFilter); - return S_OK; - } - } - This->rtLastStop = tStop; - - VideoRenderer_SendSampleData(This, pbSrcStream, cbSrcStream); - - LeaveCriticalSection(&This->csFilter); return S_OK; } -static HRESULT VideoRenderer_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt) +static HRESULT WINAPI VideoRenderer_CheckMediaType(BaseRenderer *iface, const AM_MEDIA_TYPE * pmt) { + VideoRendererImpl *This = impl_from_BaseRenderer(iface); + if (!IsEqualIID(&pmt->majortype, &MEDIATYPE_Video)) return S_FALSE; @@ -481,7 +328,6 @@ static HRESULT VideoRenderer_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB565) || IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB8)) { - VideoRendererImpl* This = iface; LONG height; if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) @@ -519,165 +365,322 @@ static HRESULT VideoRenderer_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt return S_FALSE; } -static inline VideoRendererImpl *impl_from_IMediaSeeking( IMediaSeeking *iface ) +static HRESULT WINAPI VideoRenderer_EndFlush(BaseRenderer* iface) { - return (VideoRendererImpl *)((char*)iface - FIELD_OFFSET(VideoRendererImpl, mediaSeeking.lpVtbl)); + VideoRendererImpl *This = impl_from_BaseRenderer(iface); + + TRACE("(%p)->()\n", iface); + + if (This->renderer.pMediaSample) { + ResetEvent(This->hEvent); + LeaveCriticalSection(iface->pInputPin->pin.pCritSec); + LeaveCriticalSection(&iface->csRenderLock); + LeaveCriticalSection(&iface->filter.csFilter); + WaitForSingleObject(This->hEvent, INFINITE); + EnterCriticalSection(&iface->filter.csFilter); + EnterCriticalSection(&iface->csRenderLock); + EnterCriticalSection(iface->pInputPin->pin.pCritSec); + } + if (This->renderer.filter.state == State_Paused) { + ResetEvent(This->hEvent); + } + + return BaseRendererImpl_EndFlush(iface); } -static HRESULT WINAPI VideoRendererImpl_Seeking_QueryInterface(IMediaSeeking * iface, REFIID riid, LPVOID * ppv) +static VOID WINAPI VideoRenderer_OnStopStreaming(BaseRenderer* iface) { - VideoRendererImpl *This = impl_from_IMediaSeeking(iface); + VideoRendererImpl *This = impl_from_BaseRenderer(iface); - return IUnknown_QueryInterface((IUnknown *)This, riid, ppv); + TRACE("(%p)->()\n", This); + + SetEvent(This->hEvent); + if (This->baseControlWindow.AutoShow) + /* Black it out */ + RedrawWindow(This->baseControlWindow.baseWindow.hWnd, NULL, NULL, RDW_INVALIDATE|RDW_ERASE); } -static ULONG WINAPI VideoRendererImpl_Seeking_AddRef(IMediaSeeking * iface) +static VOID WINAPI VideoRenderer_OnStartStreaming(BaseRenderer* iface) { - VideoRendererImpl *This = impl_from_IMediaSeeking(iface); + VideoRendererImpl *This = impl_from_BaseRenderer(iface); - return IUnknown_AddRef((IUnknown *)This); + TRACE("(%p)\n", This); + + if (This->renderer.pInputPin->pin.pConnectedTo && (This->renderer.filter.state == State_Stopped || !This->renderer.pInputPin->end_of_stream)) + { + if (This->renderer.filter.state == State_Stopped) + { + ResetEvent(This->hEvent); + VideoRenderer_AutoShowWindow(This); + } + } } -static ULONG WINAPI VideoRendererImpl_Seeking_Release(IMediaSeeking * iface) +static LPWSTR WINAPI VideoRenderer_GetClassWindowStyles(BaseWindow *This, DWORD *pClassStyles, DWORD *pWindowStyles, DWORD *pWindowStylesEx) { - VideoRendererImpl *This = impl_from_IMediaSeeking(iface); + static const WCHAR classnameW[] = { 'W','i','n','e',' ','A','c','t','i','v','e','M','o','v','i','e',' ','C','l','a','s','s',0 }; - return IUnknown_Release((IUnknown *)This); + *pClassStyles = 0; + *pWindowStyles = WS_SIZEBOX; + *pWindowStylesEx = 0; + + return (LPWSTR)classnameW; } -static const IMediaSeekingVtbl VideoRendererImpl_Seeking_Vtbl = +static RECT WINAPI VideoRenderer_GetDefaultRect(BaseWindow *iface) { - VideoRendererImpl_Seeking_QueryInterface, - VideoRendererImpl_Seeking_AddRef, - VideoRendererImpl_Seeking_Release, - MediaSeekingImpl_GetCapabilities, - MediaSeekingImpl_CheckCapabilities, - MediaSeekingImpl_IsFormatSupported, - MediaSeekingImpl_QueryPreferredFormat, - MediaSeekingImpl_GetTimeFormat, - MediaSeekingImpl_IsUsingTimeFormat, - MediaSeekingImpl_SetTimeFormat, - MediaSeekingImpl_GetDuration, - MediaSeekingImpl_GetStopPosition, - MediaSeekingImpl_GetCurrentPosition, - MediaSeekingImpl_ConvertTimeFormat, - MediaSeekingImpl_SetPositions, - MediaSeekingImpl_GetPositions, - MediaSeekingImpl_GetAvailable, - MediaSeekingImpl_SetRate, - MediaSeekingImpl_GetRate, - MediaSeekingImpl_GetPreroll + VideoRendererImpl *This = impl_from_BaseWindow(iface); + static RECT defRect; + + defRect.left = defRect.top = 0; + defRect.right = This->VideoWidth; + defRect.bottom = This->VideoHeight; + + return defRect; +} + +static BOOL WINAPI VideoRenderer_OnSize(BaseWindow *iface, LONG Width, LONG Height) +{ + VideoRendererImpl *This = impl_from_BaseWindow(iface); + + TRACE("WM_SIZE %d %d\n", Width, Height); + GetClientRect(iface->hWnd, &This->DestRect); + TRACE("WM_SIZING: DestRect=(%d,%d),(%d,%d)\n", + This->DestRect.left, + This->DestRect.top, + This->DestRect.right - This->DestRect.left, + This->DestRect.bottom - This->DestRect.top); + return BaseWindowImpl_OnSize(iface, Width, Height); +} + +static const BaseRendererFuncTable BaseFuncTable = { + VideoRenderer_CheckMediaType, + VideoRenderer_DoRenderSample, + /**/ + NULL, + NULL, + NULL, + VideoRenderer_OnStartStreaming, + VideoRenderer_OnStopStreaming, + NULL, + NULL, + NULL, + VideoRenderer_ShouldDrawSampleNow, + NULL, + /**/ + NULL, + NULL, + NULL, + NULL, + VideoRenderer_EndFlush, }; -static HRESULT VideoRendererImpl_Change(IBaseFilter *iface) +static const BaseWindowFuncTable renderer_BaseWindowFuncTable = { + VideoRenderer_GetClassWindowStyles, + VideoRenderer_GetDefaultRect, + NULL, + BaseControlWindowImpl_PossiblyEatMessage, + VideoRenderer_OnSize +}; + +static HRESULT WINAPI VideoRenderer_GetSourceRect(BaseControlVideo* iface, RECT *pSourceRect) { - TRACE("(%p)->()\n", iface); + VideoRendererImpl *This = impl_from_BaseControlVideo(iface); + CopyRect(pSourceRect,&This->SourceRect); return S_OK; } -HRESULT VideoRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv) +static HRESULT WINAPI VideoRenderer_GetStaticImage(BaseControlVideo* iface, LONG *pBufferSize, LONG *pDIBImage) { - HRESULT hr; - PIN_INFO piInput; - VideoRendererImpl * pVideoRenderer; + VideoRendererImpl *This = impl_from_BaseControlVideo(iface); + BITMAPINFOHEADER *bmiHeader; + LONG needed_size; + AM_MEDIA_TYPE *amt = &This->renderer.pInputPin->pin.mtCurrent; + char *ptr; - TRACE("(%p, %p)\n", pUnkOuter, ppv); + FIXME("(%p/%p)->(%p, %p): partial stub\n", This, iface, pBufferSize, pDIBImage); - *ppv = NULL; + EnterCriticalSection(&This->renderer.filter.csFilter); - pVideoRenderer = CoTaskMemAlloc(sizeof(VideoRendererImpl)); - pVideoRenderer->pUnkOuter = pUnkOuter; - pVideoRenderer->bUnkOuterValid = FALSE; - pVideoRenderer->bAggregatable = FALSE; - pVideoRenderer->IInner_vtbl = &IInner_VTable; - - pVideoRenderer->lpVtbl = &VideoRenderer_Vtbl; - pVideoRenderer->IBasicVideo_vtbl = &IBasicVideo_VTable; - pVideoRenderer->IVideoWindow_vtbl = &IVideoWindow_VTable; - - pVideoRenderer->refCount = 1; - InitializeCriticalSection(&pVideoRenderer->csFilter); - pVideoRenderer->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": VideoRendererImpl.csFilter"); - pVideoRenderer->state = State_Stopped; - pVideoRenderer->pClock = NULL; - pVideoRenderer->init = 0; - pVideoRenderer->AutoShow = 1; - pVideoRenderer->rtLastStop = -1; - ZeroMemory(&pVideoRenderer->filterInfo, sizeof(FILTER_INFO)); - ZeroMemory(&pVideoRenderer->SourceRect, sizeof(RECT)); - ZeroMemory(&pVideoRenderer->DestRect, sizeof(RECT)); - ZeroMemory(&pVideoRenderer->WindowPos, sizeof(RECT)); - pVideoRenderer->hWndMsgDrain = NULL; - - /* construct input pin */ - piInput.dir = PINDIR_INPUT; - piInput.pFilter = (IBaseFilter *)pVideoRenderer; - lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0])); - - hr = InputPin_Construct(&VideoRenderer_InputPin_Vtbl, &piInput, VideoRenderer_Sample, (LPVOID)pVideoRenderer, VideoRenderer_QueryAccept, NULL, &pVideoRenderer->csFilter, NULL, (IPin **)&pVideoRenderer->pInputPin); - - if (SUCCEEDED(hr)) + if (!This->renderer.pMediaSample) { - MediaSeekingImpl_Init((IBaseFilter*)pVideoRenderer, VideoRendererImpl_Change, VideoRendererImpl_Change, VideoRendererImpl_Change, &pVideoRenderer->mediaSeeking, &pVideoRenderer->csFilter); - pVideoRenderer->mediaSeeking.lpVtbl = &VideoRendererImpl_Seeking_Vtbl; + LeaveCriticalSection(&This->renderer.filter.csFilter); + return (This->renderer.filter.state == State_Paused ? E_UNEXPECTED : VFW_E_NOT_PAUSED); + } - pVideoRenderer->sample_held = NULL; - *ppv = pVideoRenderer; + if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo)) + { + bmiHeader = &((VIDEOINFOHEADER *)amt->pbFormat)->bmiHeader; + } + else if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo2)) + { + bmiHeader = &((VIDEOINFOHEADER2 *)amt->pbFormat)->bmiHeader; } else { - pVideoRenderer->csFilter.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&pVideoRenderer->csFilter); - CoTaskMemFree(pVideoRenderer); + FIXME("Unknown type %s\n", debugstr_guid(&amt->subtype)); + LeaveCriticalSection(&This->renderer.filter.csFilter); + return VFW_E_RUNTIME_ERROR; } - if (!CreateRenderingSubsystem(pVideoRenderer)) + needed_size = bmiHeader->biSize; + needed_size += IMediaSample_GetActualDataLength(This->renderer.pMediaSample); + + if (!pDIBImage) + { + *pBufferSize = needed_size; + LeaveCriticalSection(&This->renderer.filter.csFilter); + return S_OK; + } + + if (needed_size < *pBufferSize) + { + ERR("Buffer too small %u/%u\n", needed_size, *pBufferSize); + LeaveCriticalSection(&This->renderer.filter.csFilter); + return E_FAIL; + } + *pBufferSize = needed_size; + + memcpy(pDIBImage, bmiHeader, bmiHeader->biSize); + IMediaSample_GetPointer(This->renderer.pMediaSample, (BYTE **)&ptr); + memcpy((char *)pDIBImage + bmiHeader->biSize, ptr, IMediaSample_GetActualDataLength(This->renderer.pMediaSample)); + + LeaveCriticalSection(&This->renderer.filter.csFilter); + return S_OK; +} + +static HRESULT WINAPI VideoRenderer_GetTargetRect(BaseControlVideo* iface, RECT *pTargetRect) +{ + VideoRendererImpl *This = impl_from_BaseControlVideo(iface); + CopyRect(pTargetRect,&This->DestRect); + return S_OK; +} + +static VIDEOINFOHEADER* WINAPI VideoRenderer_GetVideoFormat(BaseControlVideo* iface) +{ + VideoRendererImpl *This = impl_from_BaseControlVideo(iface); + AM_MEDIA_TYPE *pmt; + + TRACE("(%p/%p)\n", This, iface); + + pmt = &This->renderer.pInputPin->pin.mtCurrent; + if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) { + return (VIDEOINFOHEADER*)pmt->pbFormat; + } else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2)) { + static VIDEOINFOHEADER vih; + VIDEOINFOHEADER2 *vih2 = (VIDEOINFOHEADER2*)pmt->pbFormat; + memcpy(&vih,vih2,sizeof(VIDEOINFOHEADER)); + memcpy(&vih.bmiHeader, &vih2->bmiHeader, sizeof(BITMAPINFOHEADER)); + return &vih; + } else { + ERR("Unknown format type %s\n", qzdebugstr_guid(&pmt->formattype)); + return NULL; + } +} + +static HRESULT WINAPI VideoRenderer_IsDefaultSourceRect(BaseControlVideo* iface) +{ + VideoRendererImpl *This = impl_from_BaseControlVideo(iface); + FIXME("(%p/%p)->(): stub !!!\n", This, iface); + + return S_OK; +} + +static HRESULT WINAPI VideoRenderer_IsDefaultTargetRect(BaseControlVideo* iface) +{ + VideoRendererImpl *This = impl_from_BaseControlVideo(iface); + FIXME("(%p/%p)->(): stub !!!\n", This, iface); + + return S_OK; +} + +static HRESULT WINAPI VideoRenderer_SetDefaultSourceRect(BaseControlVideo* iface) +{ + VideoRendererImpl *This = impl_from_BaseControlVideo(iface); + + This->SourceRect.left = 0; + This->SourceRect.top = 0; + This->SourceRect.right = This->VideoWidth; + This->SourceRect.bottom = This->VideoHeight; + + return S_OK; +} + +static HRESULT WINAPI VideoRenderer_SetDefaultTargetRect(BaseControlVideo* iface) +{ + VideoRendererImpl *This = impl_from_BaseControlVideo(iface); + RECT rect; + + if (!GetClientRect(This->baseControlWindow.baseWindow.hWnd, &rect)) return E_FAIL; - pVideoRenderer->blocked = CreateEventW(NULL, FALSE, FALSE, NULL); - if (!pVideoRenderer->blocked) - { - hr = HRESULT_FROM_WIN32(GetLastError()); - IUnknown_Release((IUnknown *)pVideoRenderer); - } + This->DestRect.left = 0; + This->DestRect.top = 0; + This->DestRect.right = rect.right; + This->DestRect.bottom = rect.bottom; - return hr; + return S_OK; } -HRESULT VideoRendererDefault_create(IUnknown * pUnkOuter, LPVOID * ppv) +static HRESULT WINAPI VideoRenderer_SetSourceRect(BaseControlVideo* iface, RECT *pSourceRect) { - /* TODO: Attempt to use the VMR-7 renderer instead when possible */ - return VideoRenderer_create(pUnkOuter, ppv); + VideoRendererImpl *This = impl_from_BaseControlVideo(iface); + CopyRect(&This->SourceRect,pSourceRect); + return S_OK; } -static HRESULT WINAPI VideoRendererInner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv) +static HRESULT WINAPI VideoRenderer_SetTargetRect(BaseControlVideo* iface, RECT *pTargetRect) { - ICOM_THIS_MULTI(VideoRendererImpl, IInner_vtbl, iface); + VideoRendererImpl *This = impl_from_BaseControlVideo(iface); + CopyRect(&This->DestRect,pTargetRect); + return S_OK; +} + +static const BaseControlVideoFuncTable renderer_BaseControlVideoFuncTable = { + VideoRenderer_GetSourceRect, + VideoRenderer_GetStaticImage, + VideoRenderer_GetTargetRect, + VideoRenderer_GetVideoFormat, + VideoRenderer_IsDefaultSourceRect, + VideoRenderer_IsDefaultTargetRect, + VideoRenderer_SetDefaultSourceRect, + VideoRenderer_SetDefaultTargetRect, + VideoRenderer_SetSourceRect, + VideoRenderer_SetTargetRect +}; + +static inline VideoRendererImpl *impl_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, VideoRendererImpl, IUnknown_inner); +} + +static HRESULT WINAPI VideoRendererInner_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) +{ + VideoRendererImpl *This = impl_from_IUnknown(iface); + TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv); - if (This->bAggregatable) - This->bUnkOuterValid = TRUE; - *ppv = NULL; if (IsEqualIID(riid, &IID_IUnknown)) - *ppv = &This->IInner_vtbl; - else if (IsEqualIID(riid, &IID_IPersist)) - *ppv = This; - else if (IsEqualIID(riid, &IID_IMediaFilter)) - *ppv = This; - else if (IsEqualIID(riid, &IID_IBaseFilter)) - *ppv = This; + *ppv = &This->IUnknown_inner; else if (IsEqualIID(riid, &IID_IBasicVideo)) - *ppv = &This->IBasicVideo_vtbl; + *ppv = &This->baseControlVideo.IBasicVideo_iface; else if (IsEqualIID(riid, &IID_IVideoWindow)) - *ppv = &This->IVideoWindow_vtbl; - else if (IsEqualIID(riid, &IID_IMediaSeeking)) - *ppv = &This->mediaSeeking; + *ppv = &This->baseControlWindow.IVideoWindow_iface; + else if (IsEqualIID(riid, &IID_IAMFilterMiscFlags)) + *ppv = &This->IAMFilterMiscFlags_iface; + else + { + HRESULT hr; + hr = BaseRendererImpl_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv); + if (SUCCEEDED(hr)) + return hr; + } if (*ppv) { - IUnknown_AddRef((IUnknown *)(*ppv)); + IUnknown_AddRef((IUnknown *)*ppv); return S_OK; } @@ -687,53 +690,35 @@ static HRESULT WINAPI VideoRendererInner_QueryInterface(IUnknown * iface, REFIID return E_NOINTERFACE; } -static ULONG WINAPI VideoRendererInner_AddRef(IUnknown * iface) +static ULONG WINAPI VideoRendererInner_AddRef(IUnknown *iface) { - ICOM_THIS_MULTI(VideoRendererImpl, IInner_vtbl, iface); - ULONG refCount = InterlockedIncrement(&This->refCount); + VideoRendererImpl *This = impl_from_IUnknown(iface); + ULONG refCount = BaseFilterImpl_AddRef(&This->renderer.filter.IBaseFilter_iface); - TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1); + TRACE("(%p)->(): new ref = %d\n", This, refCount); return refCount; } -static ULONG WINAPI VideoRendererInner_Release(IUnknown * iface) +static ULONG WINAPI VideoRendererInner_Release(IUnknown *iface) { - ICOM_THIS_MULTI(VideoRendererImpl, IInner_vtbl, iface); - ULONG refCount = InterlockedDecrement(&This->refCount); + VideoRendererImpl *This = impl_from_IUnknown(iface); + ULONG refCount = BaseRendererImpl_Release(&This->renderer.filter.IBaseFilter_iface); - TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1); + TRACE("(%p)->(): new ref = %d\n", This, refCount); if (!refCount) { - IPin *pConnectedTo; - - DestroyWindow(This->hWnd); - PostThreadMessageA(This->ThreadID, WM_QUIT, 0, 0); + BaseControlWindow_Destroy(&This->baseControlWindow); + BaseControlVideo_Destroy(&This->baseControlVideo); + PostThreadMessageW(This->ThreadID, WM_QUIT, 0, 0); WaitForSingleObject(This->hThread, INFINITE); CloseHandle(This->hThread); CloseHandle(This->hEvent); - if (This->pClock) - IReferenceClock_Release(This->pClock); - - if (SUCCEEDED(IPin_ConnectedTo((IPin *)This->pInputPin, &pConnectedTo))) - { - IPin_Disconnect(pConnectedTo); - IPin_Release(pConnectedTo); - } - IPin_Disconnect((IPin *)This->pInputPin); - - IPin_Release((IPin *)This->pInputPin); - - This->lpVtbl = NULL; - - This->csFilter.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&This->csFilter); - TRACE("Destroying Video Renderer\n"); CoTaskMemFree(This); - + return 0; } else @@ -749,1521 +734,348 @@ static const IUnknownVtbl IInner_VTable = static HRESULT WINAPI VideoRenderer_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv) { - VideoRendererImpl *This = (VideoRendererImpl *)iface; - - if (This->bAggregatable) - This->bUnkOuterValid = TRUE; - - if (This->pUnkOuter) - { - if (This->bAggregatable) - return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv); - - if (IsEqualIID(riid, &IID_IUnknown)) - { - HRESULT hr; - - IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl)); - hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv); - IUnknown_Release((IUnknown *)&(This->IInner_vtbl)); - This->bAggregatable = TRUE; - return hr; - } - - *ppv = NULL; - return E_NOINTERFACE; - } - - return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv); + VideoRendererImpl *This = impl_from_IBaseFilter(iface); + return IUnknown_QueryInterface(This->outer_unk, riid, ppv); } static ULONG WINAPI VideoRenderer_AddRef(IBaseFilter * iface) { - VideoRendererImpl *This = (VideoRendererImpl *)iface; - - if (This->pUnkOuter && This->bUnkOuterValid) - return IUnknown_AddRef(This->pUnkOuter); - return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl)); + VideoRendererImpl *This = impl_from_IBaseFilter(iface); + return IUnknown_AddRef(This->outer_unk); } static ULONG WINAPI VideoRenderer_Release(IBaseFilter * iface) { - VideoRendererImpl *This = (VideoRendererImpl *)iface; - - if (This->pUnkOuter && This->bUnkOuterValid) - return IUnknown_Release(This->pUnkOuter); - return IUnknown_Release((IUnknown *)&(This->IInner_vtbl)); -} - -/** IPersist methods **/ - -static HRESULT WINAPI VideoRenderer_GetClassID(IBaseFilter * iface, CLSID * pClsid) -{ - VideoRendererImpl *This = (VideoRendererImpl *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, pClsid); - - *pClsid = CLSID_VideoRenderer; - - return S_OK; + VideoRendererImpl *This = impl_from_IBaseFilter(iface); + return IUnknown_Release(This->outer_unk); } /** IMediaFilter methods **/ -static HRESULT WINAPI VideoRenderer_Stop(IBaseFilter * iface) -{ - VideoRendererImpl *This = (VideoRendererImpl *)iface; - - TRACE("(%p/%p)->()\n", This, iface); - - EnterCriticalSection(&This->csFilter); - { - This->state = State_Stopped; - SetEvent(This->hEvent); - SetEvent(This->blocked); - } - LeaveCriticalSection(&This->csFilter); - - return S_OK; -} - static HRESULT WINAPI VideoRenderer_Pause(IBaseFilter * iface) { - VideoRendererImpl *This = (VideoRendererImpl *)iface; - + VideoRendererImpl *This = impl_from_IBaseFilter(iface); + TRACE("(%p/%p)->()\n", This, iface); - EnterCriticalSection(&This->csFilter); - if (This->state != State_Paused) + EnterCriticalSection(&This->renderer.csRenderLock); + if (This->renderer.filter.state != State_Paused) { - if (This->state == State_Stopped) + if (This->renderer.filter.state == State_Stopped) { - This->pInputPin->end_of_stream = 0; + This->renderer.pInputPin->end_of_stream = 0; ResetEvent(This->hEvent); + VideoRenderer_AutoShowWindow(This); } - This->state = State_Paused; - ResetEvent(This->blocked); + ResetEvent(This->renderer.RenderEvent); + This->renderer.filter.state = State_Paused; } - LeaveCriticalSection(&This->csFilter); + LeaveCriticalSection(&This->renderer.csRenderLock); return S_OK; } -static HRESULT WINAPI VideoRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tStart) -{ - VideoRendererImpl *This = (VideoRendererImpl *)iface; - - TRACE("(%p/%p)->(%s)\n", This, iface, wine_dbgstr_longlong(tStart)); - - EnterCriticalSection(&This->csFilter); - if (This->state != State_Running) - { - if (This->state == State_Stopped) - { - This->pInputPin->end_of_stream = 0; - ResetEvent(This->hEvent); - } - SetEvent(This->blocked); - - This->rtStreamStart = tStart; - This->state = State_Running; - } - LeaveCriticalSection(&This->csFilter); - - return S_OK; -} - -static HRESULT WINAPI VideoRenderer_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState) -{ - VideoRendererImpl *This = (VideoRendererImpl *)iface; - HRESULT hr; - - TRACE("(%p/%p)->(%d, %p)\n", This, iface, dwMilliSecsTimeout, pState); - - if (WaitForSingleObject(This->hEvent, dwMilliSecsTimeout) == WAIT_TIMEOUT) - hr = VFW_S_STATE_INTERMEDIATE; - else - hr = S_OK; - - EnterCriticalSection(&This->csFilter); - { - *pState = This->state; - } - LeaveCriticalSection(&This->csFilter); - - return hr; -} - -static HRESULT WINAPI VideoRenderer_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock) -{ - VideoRendererImpl *This = (VideoRendererImpl *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, pClock); - - EnterCriticalSection(&This->csFilter); - { - if (This->pClock) - IReferenceClock_Release(This->pClock); - This->pClock = pClock; - if (This->pClock) - IReferenceClock_AddRef(This->pClock); - } - LeaveCriticalSection(&This->csFilter); - - return S_OK; -} - -static HRESULT WINAPI VideoRenderer_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock) -{ - VideoRendererImpl *This = (VideoRendererImpl *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, ppClock); - - EnterCriticalSection(&This->csFilter); - { - *ppClock = This->pClock; - if (This->pClock) - IReferenceClock_AddRef(This->pClock); - } - LeaveCriticalSection(&This->csFilter); - - return S_OK; -} - -/** IBaseFilter implementation **/ - -static HRESULT VideoRenderer_GetPin(IBaseFilter *iface, ULONG pos, IPin **pin, DWORD *lastsynctick) -{ - VideoRendererImpl *This = (VideoRendererImpl *)iface; - - /* Our pins are static, not changing so setting static tick count is ok */ - *lastsynctick = 0; - - if (pos >= 1) - return S_FALSE; - - *pin = (IPin *)This->pInputPin; - IPin_AddRef(*pin); - return S_OK; -} - -static HRESULT WINAPI VideoRenderer_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum) -{ - VideoRendererImpl *This = (VideoRendererImpl *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum); - - return IEnumPinsImpl_Construct(ppEnum, VideoRenderer_GetPin, iface); -} - -static HRESULT WINAPI VideoRenderer_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin) -{ - VideoRendererImpl *This = (VideoRendererImpl *)iface; - - FIXME("(%p/%p)->(%p,%p): stub !!!\n", This, iface, debugstr_w(Id), ppPin); - - /* FIXME: critical section */ - - return E_NOTIMPL; -} - -static HRESULT WINAPI VideoRenderer_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo) -{ - VideoRendererImpl *This = (VideoRendererImpl *)iface; - - TRACE("(%p/%p)->(%p)\n", This, iface, pInfo); - - strcpyW(pInfo->achName, This->filterInfo.achName); - pInfo->pGraph = This->filterInfo.pGraph; - - if (pInfo->pGraph) - IFilterGraph_AddRef(pInfo->pGraph); - - return S_OK; -} - -static HRESULT WINAPI VideoRenderer_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName) -{ - VideoRendererImpl *This = (VideoRendererImpl *)iface; - - TRACE("(%p/%p)->(%p, %s)\n", This, iface, pGraph, debugstr_w(pName)); - - EnterCriticalSection(&This->csFilter); - { - if (pName) - strcpyW(This->filterInfo.achName, pName); - else - *This->filterInfo.achName = '\0'; - This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */ - } - LeaveCriticalSection(&This->csFilter); - - return S_OK; -} - -static HRESULT WINAPI VideoRenderer_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo) -{ - VideoRendererImpl *This = (VideoRendererImpl *)iface; - TRACE("(%p/%p)->(%p)\n", This, iface, pVendorInfo); - return E_NOTIMPL; -} - static const IBaseFilterVtbl VideoRenderer_Vtbl = { VideoRenderer_QueryInterface, VideoRenderer_AddRef, VideoRenderer_Release, - VideoRenderer_GetClassID, - VideoRenderer_Stop, + BaseFilterImpl_GetClassID, + BaseRendererImpl_Stop, VideoRenderer_Pause, - VideoRenderer_Run, - VideoRenderer_GetState, - VideoRenderer_SetSyncSource, - VideoRenderer_GetSyncSource, - VideoRenderer_EnumPins, - VideoRenderer_FindPin, - VideoRenderer_QueryFilterInfo, - VideoRenderer_JoinFilterGraph, - VideoRenderer_QueryVendorInfo -}; - -static HRESULT WINAPI VideoRenderer_InputPin_EndOfStream(IPin * iface) -{ - InputPin* This = (InputPin*)iface; - IMediaEventSink* pEventSink; - HRESULT hr; - - TRACE("(%p/%p)->()\n", This, iface); - - hr = IFilterGraph_QueryInterface(((VideoRendererImpl*)This->pin.pinInfo.pFilter)->filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink); - if (SUCCEEDED(hr)) - { - hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, 0); - IMediaEventSink_Release(pEventSink); - } - - return hr; -} - -static HRESULT WINAPI VideoRenderer_InputPin_BeginFlush(IPin * iface) -{ - InputPin* This = (InputPin*)iface; - VideoRendererImpl *pVideoRenderer = (VideoRendererImpl *)This->pin.pinInfo.pFilter; - HRESULT hr; - - TRACE("(%p/%p)->()\n", This, iface); - - EnterCriticalSection(This->pin.pCritSec); - if (pVideoRenderer->state == State_Paused) - SetEvent(pVideoRenderer->blocked); - - hr = InputPin_BeginFlush(iface); - LeaveCriticalSection(This->pin.pCritSec); - - return hr; -} - -static HRESULT WINAPI VideoRenderer_InputPin_EndFlush(IPin * iface) -{ - InputPin* This = (InputPin*)iface; - VideoRendererImpl *pVideoRenderer = (VideoRendererImpl *)This->pin.pinInfo.pFilter; - HRESULT hr; - - TRACE("(%p/%p)->()\n", This, iface); - - EnterCriticalSection(This->pin.pCritSec); - if (pVideoRenderer->state == State_Paused) - ResetEvent(pVideoRenderer->blocked); - - hr = InputPin_EndFlush(iface); - LeaveCriticalSection(This->pin.pCritSec); - - return hr; -} - -static const IPinVtbl VideoRenderer_InputPin_Vtbl = -{ - InputPin_QueryInterface, - IPinImpl_AddRef, - InputPin_Release, - InputPin_Connect, - InputPin_ReceiveConnection, - IPinImpl_Disconnect, - IPinImpl_ConnectedTo, - IPinImpl_ConnectionMediaType, - IPinImpl_QueryPinInfo, - IPinImpl_QueryDirection, - IPinImpl_QueryId, - IPinImpl_QueryAccept, - IPinImpl_EnumMediaTypes, - IPinImpl_QueryInternalConnections, - VideoRenderer_InputPin_EndOfStream, - VideoRenderer_InputPin_BeginFlush, - VideoRenderer_InputPin_EndFlush, - InputPin_NewSegment + BaseRendererImpl_Run, + BaseRendererImpl_GetState, + BaseRendererImpl_SetSyncSource, + BaseFilterImpl_GetSyncSource, + BaseFilterImpl_EnumPins, + BaseRendererImpl_FindPin, + BaseFilterImpl_QueryFilterInfo, + BaseFilterImpl_JoinFilterGraph, + BaseFilterImpl_QueryVendorInfo }; /*** IUnknown methods ***/ -static HRESULT WINAPI Basicvideo_QueryInterface(IBasicVideo *iface, - REFIID riid, - LPVOID*ppvObj) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); +static HRESULT WINAPI BasicVideo_QueryInterface(IBasicVideo *iface, REFIID riid, LPVOID *ppvObj) +{ + VideoRendererImpl *This = impl_from_IBasicVideo(iface); TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); - return VideoRenderer_QueryInterface((IBaseFilter*)This, riid, ppvObj); + return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj); } -static ULONG WINAPI Basicvideo_AddRef(IBasicVideo *iface) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); +static ULONG WINAPI BasicVideo_AddRef(IBasicVideo *iface) +{ + VideoRendererImpl *This = impl_from_IBasicVideo(iface); TRACE("(%p/%p)->()\n", This, iface); - return VideoRenderer_AddRef((IBaseFilter*)This); + return IUnknown_AddRef(This->outer_unk); } -static ULONG WINAPI Basicvideo_Release(IBasicVideo *iface) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); +static ULONG WINAPI BasicVideo_Release(IBasicVideo *iface) +{ + VideoRendererImpl *This = impl_from_IBasicVideo(iface); TRACE("(%p/%p)->()\n", This, iface); - return VideoRenderer_Release((IBaseFilter*)This); + return IUnknown_Release(This->outer_unk); } -/*** IDispatch methods ***/ -static HRESULT WINAPI Basicvideo_GetTypeInfoCount(IBasicVideo *iface, - UINT*pctinfo) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo); - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_GetTypeInfo(IBasicVideo *iface, - UINT iTInfo, - LCID lcid, - ITypeInfo**ppTInfo) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - FIXME("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo); - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_GetIDsOfNames(IBasicVideo *iface, - REFIID riid, - LPOLESTR*rgszNames, - UINT cNames, - LCID lcid, - DISPID*rgDispId) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - FIXME("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId); - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_Invoke(IBasicVideo *iface, - DISPID dispIdMember, - REFIID riid, - LCID lcid, - WORD wFlags, - DISPPARAMS*pDispParams, - VARIANT*pVarResult, - EXCEPINFO*pExepInfo, - UINT*puArgErr) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - FIXME("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr); - - return S_OK; -} - -/*** IBasicVideo methods ***/ -static HRESULT WINAPI Basicvideo_get_AvgTimePerFrame(IBasicVideo *iface, - REFTIME *pAvgTimePerFrame) { - AM_MEDIA_TYPE *pmt; - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - if (!This->pInputPin->pin.pConnectedTo) - return VFW_E_NOT_CONNECTED; - - TRACE("(%p/%p)->(%p)\n", This, iface, pAvgTimePerFrame); - - pmt = &This->pInputPin->pin.mtCurrent; - if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) { - VIDEOINFOHEADER *vih = (VIDEOINFOHEADER*)pmt->pbFormat; - *pAvgTimePerFrame = vih->AvgTimePerFrame; - } else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2)) { - VIDEOINFOHEADER2 *vih = (VIDEOINFOHEADER2*)pmt->pbFormat; - *pAvgTimePerFrame = vih->AvgTimePerFrame; - } else { - ERR("Unknown format type %s\n", qzdebugstr_guid(&pmt->formattype)); - *pAvgTimePerFrame = 0; - } - return S_OK; -} - -static HRESULT WINAPI Basicvideo_get_BitRate(IBasicVideo *iface, - LONG *pBitRate) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pBitRate); - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_get_BitErrorRate(IBasicVideo *iface, - LONG *pBitErrorRate) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pBitErrorRate); - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_get_VideoWidth(IBasicVideo *iface, - LONG *pVideoWidth) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - TRACE("(%p/%p)->(%p)\n", This, iface, pVideoWidth); - - *pVideoWidth = This->VideoWidth; - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_get_VideoHeight(IBasicVideo *iface, - LONG *pVideoHeight) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - TRACE("(%p/%p)->(%p)\n", This, iface, pVideoHeight); - - *pVideoHeight = This->VideoHeight; - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_put_SourceLeft(IBasicVideo *iface, - LONG SourceLeft) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - TRACE("(%p/%p)->(%d)\n", This, iface, SourceLeft); - - This->SourceRect.left = SourceLeft; - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_get_SourceLeft(IBasicVideo *iface, - LONG *pSourceLeft) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - TRACE("(%p/%p)->(%p)\n", This, iface, pSourceLeft); - - *pSourceLeft = This->SourceRect.left; - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_put_SourceWidth(IBasicVideo *iface, - LONG SourceWidth) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - TRACE("(%p/%p)->(%d)\n", This, iface, SourceWidth); - - This->SourceRect.right = This->SourceRect.left + SourceWidth; - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_get_SourceWidth(IBasicVideo *iface, - LONG *pSourceWidth) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - TRACE("(%p/%p)->(%p)\n", This, iface, pSourceWidth); - - *pSourceWidth = This->SourceRect.right - This->SourceRect.left; - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_put_SourceTop(IBasicVideo *iface, - LONG SourceTop) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - TRACE("(%p/%p)->(%d)\n", This, iface, SourceTop); - - This->SourceRect.top = SourceTop; - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_get_SourceTop(IBasicVideo *iface, - LONG *pSourceTop) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - TRACE("(%p/%p)->(%p)\n", This, iface, pSourceTop); - - *pSourceTop = This->SourceRect.top; - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_put_SourceHeight(IBasicVideo *iface, - LONG SourceHeight) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - TRACE("(%p/%p)->(%d)\n", This, iface, SourceHeight); - - This->SourceRect.bottom = This->SourceRect.top + SourceHeight; - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_get_SourceHeight(IBasicVideo *iface, - LONG *pSourceHeight) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - TRACE("(%p/%p)->(%p)\n", This, iface, pSourceHeight); - - *pSourceHeight = This->SourceRect.bottom - This->SourceRect.top; - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_put_DestinationLeft(IBasicVideo *iface, - LONG DestinationLeft) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - TRACE("(%p/%p)->(%d)\n", This, iface, DestinationLeft); - - This->DestRect.left = DestinationLeft; - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_get_DestinationLeft(IBasicVideo *iface, - LONG *pDestinationLeft) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationLeft); - - *pDestinationLeft = This->DestRect.left; - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_put_DestinationWidth(IBasicVideo *iface, - LONG DestinationWidth) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - TRACE("(%p/%p)->(%d)\n", This, iface, DestinationWidth); - - This->DestRect.right = This->DestRect.left + DestinationWidth; - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_get_DestinationWidth(IBasicVideo *iface, - LONG *pDestinationWidth) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationWidth); - - *pDestinationWidth = This->DestRect.right - This->DestRect.left; - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_put_DestinationTop(IBasicVideo *iface, - LONG DestinationTop) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - TRACE("(%p/%p)->(%d)\n", This, iface, DestinationTop); - - This->DestRect.top = DestinationTop; - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_get_DestinationTop(IBasicVideo *iface, - LONG *pDestinationTop) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationTop); - - *pDestinationTop = This->DestRect.top; - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_put_DestinationHeight(IBasicVideo *iface, - LONG DestinationHeight) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - TRACE("(%p/%p)->(%d)\n", This, iface, DestinationHeight); - - This->DestRect.right = This->DestRect.left + DestinationHeight; - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_get_DestinationHeight(IBasicVideo *iface, - LONG *pDestinationHeight) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationHeight); - - *pDestinationHeight = This->DestRect.right - This->DestRect.left; - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_SetSourcePosition(IBasicVideo *iface, - LONG Left, - LONG Top, - LONG Width, - LONG Height) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height); - - This->SourceRect.left = Left; - This->SourceRect.top = Top; - This->SourceRect.right = Left + Width; - This->SourceRect.bottom = Top + Height; - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_GetSourcePosition(IBasicVideo *iface, - LONG *pLeft, - LONG *pTop, - LONG *pWidth, - LONG *pHeight) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight); - - *pLeft = This->SourceRect.left; - *pTop = This->SourceRect.top; - *pWidth = This->SourceRect.right - This->SourceRect.left; - *pHeight = This->SourceRect.bottom - This->SourceRect.top; - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_SetDefaultSourcePosition(IBasicVideo *iface) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - TRACE("(%p/%p)->()\n", This, iface); - - This->SourceRect.left = 0; - This->SourceRect.top = 0; - This->SourceRect.right = This->VideoWidth; - This->SourceRect.bottom = This->VideoHeight; - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_SetDestinationPosition(IBasicVideo *iface, - LONG Left, - LONG Top, - LONG Width, - LONG Height) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height); - - This->DestRect.left = Left; - This->DestRect.top = Top; - This->DestRect.right = Left + Width; - This->DestRect.bottom = Top + Height; - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_GetDestinationPosition(IBasicVideo *iface, - LONG *pLeft, - LONG *pTop, - LONG *pWidth, - LONG *pHeight) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight); - - *pLeft = This->DestRect.left; - *pTop = This->DestRect.top; - *pWidth = This->DestRect.right - This->DestRect.left; - *pHeight = This->DestRect.bottom - This->DestRect.top; - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_SetDefaultDestinationPosition(IBasicVideo *iface) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - RECT rect; - - TRACE("(%p/%p)->()\n", This, iface); - - if (!GetClientRect(This->hWnd, &rect)) - return E_FAIL; - - This->SourceRect.left = 0; - This->SourceRect.top = 0; - This->SourceRect.right = rect.right; - This->SourceRect.bottom = rect.bottom; - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_GetVideoSize(IBasicVideo *iface, - LONG *pWidth, - LONG *pHeight) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight); - - *pWidth = This->VideoWidth; - *pHeight = This->VideoHeight; - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_GetVideoPaletteEntries(IBasicVideo *iface, - LONG StartIndex, - LONG Entries, - LONG *pRetrieved, - LONG *pPalette) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - FIXME("(%p/%p)->(%d, %d, %p, %p): stub !!!\n", This, iface, StartIndex, Entries, pRetrieved, pPalette); - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_GetCurrentImage(IBasicVideo *iface, - LONG *pBufferSize, - LONG *pDIBImage) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - BITMAPINFOHEADER *bmiHeader; - LONG needed_size; - AM_MEDIA_TYPE *amt = &This->pInputPin->pin.mtCurrent; - char *ptr; - - FIXME("(%p/%p)->(%p, %p): partial stub\n", This, iface, pBufferSize, pDIBImage); - - EnterCriticalSection(&This->csFilter); - - if (!This->sample_held) - { - LeaveCriticalSection(&This->csFilter); - return (This->state == State_Paused ? E_UNEXPECTED : VFW_E_NOT_PAUSED); - } - - if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo)) - { - bmiHeader = &((VIDEOINFOHEADER *)amt->pbFormat)->bmiHeader; - } - else if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo2)) - { - bmiHeader = &((VIDEOINFOHEADER2 *)amt->pbFormat)->bmiHeader; - } - else - { - FIXME("Unknown type %s\n", debugstr_guid(&amt->subtype)); - LeaveCriticalSection(&This->csFilter); - return VFW_E_RUNTIME_ERROR; - } - - needed_size = bmiHeader->biSize; - needed_size += IMediaSample_GetActualDataLength(This->sample_held); - - if (!pDIBImage) - { - *pBufferSize = needed_size; - LeaveCriticalSection(&This->csFilter); - return S_OK; - } - - if (needed_size < *pBufferSize) - { - ERR("Buffer too small %u/%u\n", needed_size, *pBufferSize); - LeaveCriticalSection(&This->csFilter); - return E_FAIL; - } - *pBufferSize = needed_size; - - memcpy(pDIBImage, bmiHeader, bmiHeader->biSize); - IMediaSample_GetPointer(This->sample_held, (BYTE **)&ptr); - memcpy((char *)pDIBImage + bmiHeader->biSize, ptr, IMediaSample_GetActualDataLength(This->sample_held)); - - LeaveCriticalSection(&This->csFilter); - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_IsUsingDefaultSource(IBasicVideo *iface) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - FIXME("(%p/%p)->(): stub !!!\n", This, iface); - - return S_OK; -} - -static HRESULT WINAPI Basicvideo_IsUsingDefaultDestination(IBasicVideo *iface) { - ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface); - - FIXME("(%p/%p)->(): stub !!!\n", This, iface); - - return S_OK; -} - - static const IBasicVideoVtbl IBasicVideo_VTable = { - Basicvideo_QueryInterface, - Basicvideo_AddRef, - Basicvideo_Release, - Basicvideo_GetTypeInfoCount, - Basicvideo_GetTypeInfo, - Basicvideo_GetIDsOfNames, - Basicvideo_Invoke, - Basicvideo_get_AvgTimePerFrame, - Basicvideo_get_BitRate, - Basicvideo_get_BitErrorRate, - Basicvideo_get_VideoWidth, - Basicvideo_get_VideoHeight, - Basicvideo_put_SourceLeft, - Basicvideo_get_SourceLeft, - Basicvideo_put_SourceWidth, - Basicvideo_get_SourceWidth, - Basicvideo_put_SourceTop, - Basicvideo_get_SourceTop, - Basicvideo_put_SourceHeight, - Basicvideo_get_SourceHeight, - Basicvideo_put_DestinationLeft, - Basicvideo_get_DestinationLeft, - Basicvideo_put_DestinationWidth, - Basicvideo_get_DestinationWidth, - Basicvideo_put_DestinationTop, - Basicvideo_get_DestinationTop, - Basicvideo_put_DestinationHeight, - Basicvideo_get_DestinationHeight, - Basicvideo_SetSourcePosition, - Basicvideo_GetSourcePosition, - Basicvideo_SetDefaultSourcePosition, - Basicvideo_SetDestinationPosition, - Basicvideo_GetDestinationPosition, - Basicvideo_SetDefaultDestinationPosition, - Basicvideo_GetVideoSize, - Basicvideo_GetVideoPaletteEntries, - Basicvideo_GetCurrentImage, - Basicvideo_IsUsingDefaultSource, - Basicvideo_IsUsingDefaultDestination + BasicVideo_QueryInterface, + BasicVideo_AddRef, + BasicVideo_Release, + BaseControlVideoImpl_GetTypeInfoCount, + BaseControlVideoImpl_GetTypeInfo, + BaseControlVideoImpl_GetIDsOfNames, + BaseControlVideoImpl_Invoke, + BaseControlVideoImpl_get_AvgTimePerFrame, + BaseControlVideoImpl_get_BitRate, + BaseControlVideoImpl_get_BitErrorRate, + BaseControlVideoImpl_get_VideoWidth, + BaseControlVideoImpl_get_VideoHeight, + BaseControlVideoImpl_put_SourceLeft, + BaseControlVideoImpl_get_SourceLeft, + BaseControlVideoImpl_put_SourceWidth, + BaseControlVideoImpl_get_SourceWidth, + BaseControlVideoImpl_put_SourceTop, + BaseControlVideoImpl_get_SourceTop, + BaseControlVideoImpl_put_SourceHeight, + BaseControlVideoImpl_get_SourceHeight, + BaseControlVideoImpl_put_DestinationLeft, + BaseControlVideoImpl_get_DestinationLeft, + BaseControlVideoImpl_put_DestinationWidth, + BaseControlVideoImpl_get_DestinationWidth, + BaseControlVideoImpl_put_DestinationTop, + BaseControlVideoImpl_get_DestinationTop, + BaseControlVideoImpl_put_DestinationHeight, + BaseControlVideoImpl_get_DestinationHeight, + BaseControlVideoImpl_SetSourcePosition, + BaseControlVideoImpl_GetSourcePosition, + BaseControlVideoImpl_SetDefaultSourcePosition, + BaseControlVideoImpl_SetDestinationPosition, + BaseControlVideoImpl_GetDestinationPosition, + BaseControlVideoImpl_SetDefaultDestinationPosition, + BaseControlVideoImpl_GetVideoSize, + BaseControlVideoImpl_GetVideoPaletteEntries, + BaseControlVideoImpl_GetCurrentImage, + BaseControlVideoImpl_IsUsingDefaultSource, + BaseControlVideoImpl_IsUsingDefaultDestination }; /*** IUnknown methods ***/ -static HRESULT WINAPI Videowindow_QueryInterface(IVideoWindow *iface, - REFIID riid, - LPVOID*ppvObj) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); +static HRESULT WINAPI VideoWindow_QueryInterface(IVideoWindow *iface, REFIID riid, LPVOID *ppvObj) +{ + VideoRendererImpl *This = impl_from_IVideoWindow(iface); TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); - return VideoRenderer_QueryInterface((IBaseFilter*)This, riid, ppvObj); + return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj); } -static ULONG WINAPI Videowindow_AddRef(IVideoWindow *iface) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); +static ULONG WINAPI VideoWindow_AddRef(IVideoWindow *iface) +{ + VideoRendererImpl *This = impl_from_IVideoWindow(iface); TRACE("(%p/%p)->()\n", This, iface); - return VideoRenderer_AddRef((IBaseFilter*)This); + return IUnknown_AddRef(This->outer_unk); } -static ULONG WINAPI Videowindow_Release(IVideoWindow *iface) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); +static ULONG WINAPI VideoWindow_Release(IVideoWindow *iface) +{ + VideoRendererImpl *This = impl_from_IVideoWindow(iface); TRACE("(%p/%p)->()\n", This, iface); - return VideoRenderer_Release((IBaseFilter*)This); + return IUnknown_Release(This->outer_unk); } -/*** IDispatch methods ***/ -static HRESULT WINAPI Videowindow_GetTypeInfoCount(IVideoWindow *iface, - UINT*pctinfo) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pctinfo); - - return S_OK; -} - -static HRESULT WINAPI Videowindow_GetTypeInfo(IVideoWindow *iface, - UINT iTInfo, - LCID lcid, - ITypeInfo**ppTInfo) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - FIXME("(%p/%p)->(%d, %d, %p): stub !!!\n", This, iface, iTInfo, lcid, ppTInfo); - - return S_OK; -} - -static HRESULT WINAPI Videowindow_GetIDsOfNames(IVideoWindow *iface, - REFIID riid, - LPOLESTR*rgszNames, - UINT cNames, - LCID lcid, - DISPID*rgDispId) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - FIXME("(%p/%p)->(%s (%p), %p, %d, %d, %p): stub !!!\n", This, iface, debugstr_guid(riid), riid, rgszNames, cNames, lcid, rgDispId); - - return S_OK; -} - -static HRESULT WINAPI Videowindow_Invoke(IVideoWindow *iface, - DISPID dispIdMember, - REFIID riid, - LCID lcid, - WORD wFlags, - DISPPARAMS*pDispParams, - VARIANT*pVarResult, - EXCEPINFO*pExepInfo, - UINT*puArgErr) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - FIXME("(%p/%p)->(%d, %s (%p), %d, %04x, %p, %p, %p, %p): stub !!!\n", This, iface, dispIdMember, debugstr_guid(riid), riid, lcid, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr); - - return S_OK; -} - -/*** IVideoWindow methods ***/ -static HRESULT WINAPI Videowindow_put_Caption(IVideoWindow *iface, - BSTR strCaption) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strCaption), strCaption); - - if (!SetWindowTextW(This->hWnd, strCaption)) - return E_FAIL; - - return S_OK; -} - -static HRESULT WINAPI Videowindow_get_Caption(IVideoWindow *iface, - BSTR *strCaption) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - TRACE("(%p/%p)->(%p)\n", This, iface, strCaption); - - GetWindowTextW(This->hWnd, (LPWSTR)strCaption, 100); - - return S_OK; -} - -static HRESULT WINAPI Videowindow_put_WindowStyle(IVideoWindow *iface, - LONG WindowStyle) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - LONG old; - - old = GetWindowLongA(This->hWnd, GWL_STYLE); - - TRACE("(%p/%p)->(%x -> %x)\n", This, iface, old, WindowStyle); - - if (WindowStyle & (WS_DISABLED|WS_HSCROLL|WS_ICONIC|WS_MAXIMIZE|WS_MINIMIZE|WS_VSCROLL)) - return E_INVALIDARG; - - SetWindowLongA(This->hWnd, GWL_STYLE, WindowStyle); - - return S_OK; -} - -static HRESULT WINAPI Videowindow_get_WindowStyle(IVideoWindow *iface, - LONG *WindowStyle) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyle); - - *WindowStyle = GetWindowLongA(This->hWnd, GWL_STYLE); - - return S_OK; -} - -static HRESULT WINAPI Videowindow_put_WindowStyleEx(IVideoWindow *iface, - LONG WindowStyleEx) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - TRACE("(%p/%p)->(%d)\n", This, iface, WindowStyleEx); - - if (!SetWindowLongA(This->hWnd, GWL_EXSTYLE, WindowStyleEx)) - return E_FAIL; - - return S_OK; -} - -static HRESULT WINAPI Videowindow_get_WindowStyleEx(IVideoWindow *iface, - LONG *WindowStyleEx) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyleEx); - - *WindowStyleEx = GetWindowLongA(This->hWnd, GWL_EXSTYLE); - - return S_OK; -} - -static HRESULT WINAPI Videowindow_put_AutoShow(IVideoWindow *iface, - LONG AutoShow) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - TRACE("(%p/%p)->(%d)\n", This, iface, AutoShow); - - This->AutoShow = AutoShow; - - return S_OK; -} - -static HRESULT WINAPI Videowindow_get_AutoShow(IVideoWindow *iface, - LONG *AutoShow) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - TRACE("(%p/%p)->(%p)\n", This, iface, AutoShow); - - *AutoShow = This->AutoShow; - - return S_OK; -} - -static HRESULT WINAPI Videowindow_put_WindowState(IVideoWindow *iface, - LONG WindowState) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - TRACE("(%p/%p)->(%d)\n", This, iface, WindowState); - ShowWindow(This->hWnd, WindowState); - return S_OK; -} - -static HRESULT WINAPI Videowindow_get_WindowState(IVideoWindow *iface, - LONG *WindowState) { - WINDOWPLACEMENT place; - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - place.length = sizeof(place); - GetWindowPlacement(This->hWnd, &place); - TRACE("(%p/%p)->(%p)\n", This, iface, WindowState); - *WindowState = place.showCmd; - - return S_OK; -} - -static HRESULT WINAPI Videowindow_put_BackgroundPalette(IVideoWindow *iface, - LONG BackgroundPalette) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - FIXME("(%p/%p)->(%d): stub !!!\n", This, iface, BackgroundPalette); - - return S_OK; -} - -static HRESULT WINAPI Videowindow_get_BackgroundPalette(IVideoWindow *iface, - LONG *pBackgroundPalette) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pBackgroundPalette); - - return S_OK; -} - -static HRESULT WINAPI Videowindow_put_Visible(IVideoWindow *iface, - LONG Visible) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - TRACE("(%p/%p)->(%d)\n", This, iface, Visible); - - ShowWindow(This->hWnd, Visible ? SW_SHOW : SW_HIDE); - - return S_OK; -} - -static HRESULT WINAPI Videowindow_get_Visible(IVideoWindow *iface, - LONG *pVisible) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - TRACE("(%p/%p)->(%p)\n", This, iface, pVisible); - - *pVisible = IsWindowVisible(This->hWnd); - - return S_OK; -} - -static HRESULT WINAPI Videowindow_put_Left(IVideoWindow *iface, - LONG Left) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - TRACE("(%p/%p)->(%d)\n", This, iface, Left); - - if (!SetWindowPos(This->hWnd, NULL, Left, This->WindowPos.top, 0, 0, SWP_NOZORDER|SWP_NOSIZE)) - return E_FAIL; - - This->WindowPos.left = Left; - - return S_OK; -} - -static HRESULT WINAPI Videowindow_get_Left(IVideoWindow *iface, - LONG *pLeft) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - TRACE("(%p/%p)->(%p)\n", This, iface, pLeft); - - *pLeft = This->WindowPos.left; - - return S_OK; -} - -static HRESULT WINAPI Videowindow_put_Width(IVideoWindow *iface, - LONG Width) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - TRACE("(%p/%p)->(%d)\n", This, iface, Width); - - if (!SetWindowPos(This->hWnd, NULL, 0, 0, Width, This->WindowPos.bottom-This->WindowPos.top, SWP_NOZORDER|SWP_NOMOVE)) - return E_FAIL; - - This->WindowPos.right = This->WindowPos.left + Width; - - return S_OK; -} - -static HRESULT WINAPI Videowindow_get_Width(IVideoWindow *iface, - LONG *pWidth) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - TRACE("(%p/%p)->(%p)\n", This, iface, pWidth); - - *pWidth = This->WindowPos.right - This->WindowPos.left; - - return S_OK; -} - -static HRESULT WINAPI Videowindow_put_Top(IVideoWindow *iface, - LONG Top) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - TRACE("(%p/%p)->(%d)\n", This, iface, Top); - - if (!SetWindowPos(This->hWnd, NULL, This->WindowPos.left, Top, 0, 0, SWP_NOZORDER|SWP_NOSIZE)) - return E_FAIL; - - This->WindowPos.top = Top; - - return S_OK; -} - -static HRESULT WINAPI Videowindow_get_Top(IVideoWindow *iface, - LONG *pTop) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - TRACE("(%p/%p)->(%p)\n", This, iface, pTop); - - *pTop = This->WindowPos.top; - - return S_OK; -} - -static HRESULT WINAPI Videowindow_put_Height(IVideoWindow *iface, - LONG Height) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - TRACE("(%p/%p)->(%d)\n", This, iface, Height); - - if (!SetWindowPos(This->hWnd, NULL, 0, 0, This->WindowPos.right-This->WindowPos.left, Height, SWP_NOZORDER|SWP_NOMOVE)) - return E_FAIL; - - This->WindowPos.bottom = This->WindowPos.top + Height; - - return S_OK; -} - -static HRESULT WINAPI Videowindow_get_Height(IVideoWindow *iface, - LONG *pHeight) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - TRACE("(%p/%p)->(%p)\n", This, iface, pHeight); - - *pHeight = This->WindowPos.bottom - This->WindowPos.top; - - return S_OK; -} - -static HRESULT WINAPI Videowindow_put_Owner(IVideoWindow *iface, - OAHWND Owner) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Owner); - - SetParent(This->hWnd, (HWND)Owner); - - return S_OK; -} - -static HRESULT WINAPI Videowindow_get_Owner(IVideoWindow *iface, - OAHWND *Owner) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - TRACE("(%p/%p)->(%p)\n", This, iface, Owner); - - *(HWND*)Owner = GetParent(This->hWnd); - - return S_OK; -} - -static HRESULT WINAPI Videowindow_put_MessageDrain(IVideoWindow *iface, - OAHWND Drain) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Drain); - - This->hWndMsgDrain = (HWND)Drain; - - return S_OK; -} - -static HRESULT WINAPI Videowindow_get_MessageDrain(IVideoWindow *iface, - OAHWND *Drain) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - TRACE("(%p/%p)->(%p)\n", This, iface, Drain); - - *Drain = (OAHWND)This->hWndMsgDrain; - - return S_OK; -} - -static HRESULT WINAPI Videowindow_get_BorderColor(IVideoWindow *iface, - LONG *Color) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, Color); - - return S_OK; -} - -static HRESULT WINAPI Videowindow_put_BorderColor(IVideoWindow *iface, - LONG Color) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - FIXME("(%p/%p)->(%d): stub !!!\n", This, iface, Color); - - return S_OK; -} - -static HRESULT WINAPI Videowindow_get_FullScreenMode(IVideoWindow *iface, - LONG *FullScreenMode) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); +static HRESULT WINAPI VideoWindow_get_FullScreenMode(IVideoWindow *iface, + LONG *FullScreenMode) +{ + VideoRendererImpl *This = impl_from_IVideoWindow(iface); FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, FullScreenMode); return S_OK; } -static HRESULT WINAPI Videowindow_put_FullScreenMode(IVideoWindow *iface, - LONG FullScreenMode) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); +static HRESULT WINAPI VideoWindow_put_FullScreenMode(IVideoWindow *iface, + LONG FullScreenMode) +{ + VideoRendererImpl *This = impl_from_IVideoWindow(iface); FIXME("(%p/%p)->(%d): stub !!!\n", This, iface, FullScreenMode); - return S_OK; -} - -static HRESULT WINAPI Videowindow_SetWindowForeground(IVideoWindow *iface, - LONG Focus) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - BOOL ret; - IPin* pPin; - HRESULT hr; - - TRACE("(%p/%p)->(%d)\n", This, iface, Focus); - - if ((Focus != FALSE) && (Focus != TRUE)) - return E_INVALIDARG; - - hr = IPin_ConnectedTo((IPin *)This->pInputPin, &pPin); - if ((hr != S_OK) || !pPin) - return VFW_E_NOT_CONNECTED; - - if (Focus) - ret = SetForegroundWindow(This->hWnd); - else - ret = SetWindowPos(This->hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); - - if (!ret) - return E_FAIL; - - return S_OK; -} - -static HRESULT WINAPI Videowindow_NotifyOwnerMessage(IVideoWindow *iface, - OAHWND hwnd, - LONG uMsg, - LONG_PTR wParam, - LONG_PTR lParam) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - TRACE("(%p/%p)->(%08lx, %d, %08lx, %08lx)\n", This, iface, hwnd, uMsg, wParam, lParam); - - if (!PostMessageA(This->hWnd, uMsg, wParam, lParam)) - return E_FAIL; - - return S_OK; -} - -static HRESULT WINAPI Videowindow_SetWindowPosition(IVideoWindow *iface, - LONG Left, - LONG Top, - LONG Width, - LONG Height) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height); - - if (!SetWindowPos(This->hWnd, NULL, Left, Top, Width, Height, SWP_NOZORDER)) - return E_FAIL; - - This->WindowPos.left = Left; - This->WindowPos.top = Top; - This->WindowPos.right = Left + Width; - This->WindowPos.bottom = Top + Height; - - return S_OK; -} - -static HRESULT WINAPI Videowindow_GetWindowPosition(IVideoWindow *iface, - LONG *pLeft, - LONG *pTop, - LONG *pWidth, - LONG *pHeight) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight); - - *pLeft = This->WindowPos.left; - *pTop = This->WindowPos.top; - *pWidth = This->WindowPos.right - This->WindowPos.left; - *pHeight = This->WindowPos.bottom - This->WindowPos.top; - - return S_OK; -} - -static HRESULT WINAPI Videowindow_GetMinIdealImageSize(IVideoWindow *iface, - LONG *pWidth, - LONG *pHeight) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - FIXME("(%p/%p)->(%p, %p): semi stub !!!\n", This, iface, pWidth, pHeight); - - *pWidth = This->VideoWidth; - *pHeight = This->VideoHeight; - - return S_OK; -} - -static HRESULT WINAPI Videowindow_GetMaxIdealImageSize(IVideoWindow *iface, - LONG *pWidth, - LONG *pHeight) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - FIXME("(%p/%p)->(%p, %p): semi stub !!!\n", This, iface, pWidth, pHeight); - - *pWidth = This->VideoWidth; - *pHeight = This->VideoHeight; - - return S_OK; -} - -static HRESULT WINAPI Videowindow_GetRestorePosition(IVideoWindow *iface, - LONG *pLeft, - LONG *pTop, - LONG *pWidth, - LONG *pHeight) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - FIXME("(%p/%p)->(%p, %p, %p, %p): stub !!!\n", This, iface, pLeft, pTop, pWidth, pHeight); - - return S_OK; -} - -static HRESULT WINAPI Videowindow_HideCursor(IVideoWindow *iface, - LONG HideCursor) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - FIXME("(%p/%p)->(%d): stub !!!\n", This, iface, HideCursor); - - return S_OK; -} - -static HRESULT WINAPI Videowindow_IsCursorHidden(IVideoWindow *iface, - LONG *CursorHidden) { - ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface); - - FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, CursorHidden); + if (FullScreenMode) { + This->baseControlWindow.baseWindow.WindowStyles = GetWindowLongW(This->baseControlWindow.baseWindow.hWnd, GWL_STYLE); + ShowWindow(This->baseControlWindow.baseWindow.hWnd, SW_HIDE); + SetParent(This->baseControlWindow.baseWindow.hWnd, 0); + SetWindowLongW(This->baseControlWindow.baseWindow.hWnd, GWL_STYLE, WS_POPUP); + SetWindowPos(This->baseControlWindow.baseWindow.hWnd,HWND_TOP,0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN),SWP_SHOWWINDOW); + GetWindowRect(This->baseControlWindow.baseWindow.hWnd, &This->DestRect); + This->WindowPos = This->DestRect; + } else { + ShowWindow(This->baseControlWindow.baseWindow.hWnd, SW_HIDE); + SetParent(This->baseControlWindow.baseWindow.hWnd, This->baseControlWindow.hwndOwner); + SetWindowLongW(This->baseControlWindow.baseWindow.hWnd, GWL_STYLE, This->baseControlWindow.baseWindow.WindowStyles); + GetClientRect(This->baseControlWindow.baseWindow.hWnd, &This->DestRect); + SetWindowPos(This->baseControlWindow.baseWindow.hWnd,0,This->DestRect.left,This->DestRect.top,This->DestRect.right,This->DestRect.bottom,SWP_NOZORDER|SWP_SHOWWINDOW); + This->WindowPos = This->DestRect; + } return S_OK; } static const IVideoWindowVtbl IVideoWindow_VTable = { - Videowindow_QueryInterface, - Videowindow_AddRef, - Videowindow_Release, - Videowindow_GetTypeInfoCount, - Videowindow_GetTypeInfo, - Videowindow_GetIDsOfNames, - Videowindow_Invoke, - Videowindow_put_Caption, - Videowindow_get_Caption, - Videowindow_put_WindowStyle, - Videowindow_get_WindowStyle, - Videowindow_put_WindowStyleEx, - Videowindow_get_WindowStyleEx, - Videowindow_put_AutoShow, - Videowindow_get_AutoShow, - Videowindow_put_WindowState, - Videowindow_get_WindowState, - Videowindow_put_BackgroundPalette, - Videowindow_get_BackgroundPalette, - Videowindow_put_Visible, - Videowindow_get_Visible, - Videowindow_put_Left, - Videowindow_get_Left, - Videowindow_put_Width, - Videowindow_get_Width, - Videowindow_put_Top, - Videowindow_get_Top, - Videowindow_put_Height, - Videowindow_get_Height, - Videowindow_put_Owner, - Videowindow_get_Owner, - Videowindow_put_MessageDrain, - Videowindow_get_MessageDrain, - Videowindow_get_BorderColor, - Videowindow_put_BorderColor, - Videowindow_get_FullScreenMode, - Videowindow_put_FullScreenMode, - Videowindow_SetWindowForeground, - Videowindow_NotifyOwnerMessage, - Videowindow_SetWindowPosition, - Videowindow_GetWindowPosition, - Videowindow_GetMinIdealImageSize, - Videowindow_GetMaxIdealImageSize, - Videowindow_GetRestorePosition, - Videowindow_HideCursor, - Videowindow_IsCursorHidden + VideoWindow_QueryInterface, + VideoWindow_AddRef, + VideoWindow_Release, + BaseControlWindowImpl_GetTypeInfoCount, + BaseControlWindowImpl_GetTypeInfo, + BaseControlWindowImpl_GetIDsOfNames, + BaseControlWindowImpl_Invoke, + BaseControlWindowImpl_put_Caption, + BaseControlWindowImpl_get_Caption, + BaseControlWindowImpl_put_WindowStyle, + BaseControlWindowImpl_get_WindowStyle, + BaseControlWindowImpl_put_WindowStyleEx, + BaseControlWindowImpl_get_WindowStyleEx, + BaseControlWindowImpl_put_AutoShow, + BaseControlWindowImpl_get_AutoShow, + BaseControlWindowImpl_put_WindowState, + BaseControlWindowImpl_get_WindowState, + BaseControlWindowImpl_put_BackgroundPalette, + BaseControlWindowImpl_get_BackgroundPalette, + BaseControlWindowImpl_put_Visible, + BaseControlWindowImpl_get_Visible, + BaseControlWindowImpl_put_Left, + BaseControlWindowImpl_get_Left, + BaseControlWindowImpl_put_Width, + BaseControlWindowImpl_get_Width, + BaseControlWindowImpl_put_Top, + BaseControlWindowImpl_get_Top, + BaseControlWindowImpl_put_Height, + BaseControlWindowImpl_get_Height, + BaseControlWindowImpl_put_Owner, + BaseControlWindowImpl_get_Owner, + BaseControlWindowImpl_put_MessageDrain, + BaseControlWindowImpl_get_MessageDrain, + BaseControlWindowImpl_get_BorderColor, + BaseControlWindowImpl_put_BorderColor, + VideoWindow_get_FullScreenMode, + VideoWindow_put_FullScreenMode, + BaseControlWindowImpl_SetWindowForeground, + BaseControlWindowImpl_NotifyOwnerMessage, + BaseControlWindowImpl_SetWindowPosition, + BaseControlWindowImpl_GetWindowPosition, + BaseControlWindowImpl_GetMinIdealImageSize, + BaseControlWindowImpl_GetMaxIdealImageSize, + BaseControlWindowImpl_GetRestorePosition, + BaseControlWindowImpl_HideCursor, + BaseControlWindowImpl_IsCursorHidden }; + +static VideoRendererImpl *impl_from_IAMFilterMiscFlags(IAMFilterMiscFlags *iface) +{ + return CONTAINING_RECORD(iface, VideoRendererImpl, IAMFilterMiscFlags_iface); +} + +static HRESULT WINAPI AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid, + void **ppv) +{ + VideoRendererImpl *This = impl_from_IAMFilterMiscFlags(iface); + return IUnknown_QueryInterface(This->outer_unk, riid, ppv); +} + +static ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface) +{ + VideoRendererImpl *This = impl_from_IAMFilterMiscFlags(iface); + return IUnknown_AddRef(This->outer_unk); +} + +static ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface) +{ + VideoRendererImpl *This = impl_from_IAMFilterMiscFlags(iface); + return IUnknown_Release(This->outer_unk); +} + +static ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface) +{ + return AM_FILTER_MISC_FLAGS_IS_RENDERER; +} + +static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = { + AMFilterMiscFlags_QueryInterface, + AMFilterMiscFlags_AddRef, + AMFilterMiscFlags_Release, + AMFilterMiscFlags_GetMiscFlags +}; + +HRESULT VideoRenderer_create(IUnknown *pUnkOuter, void **ppv) +{ + HRESULT hr; + VideoRendererImpl * pVideoRenderer; + + TRACE("(%p, %p)\n", pUnkOuter, ppv); + + *ppv = NULL; + + pVideoRenderer = CoTaskMemAlloc(sizeof(VideoRendererImpl)); + pVideoRenderer->IUnknown_inner.lpVtbl = &IInner_VTable; + pVideoRenderer->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_Vtbl; + + pVideoRenderer->init = 0; + ZeroMemory(&pVideoRenderer->SourceRect, sizeof(RECT)); + ZeroMemory(&pVideoRenderer->DestRect, sizeof(RECT)); + ZeroMemory(&pVideoRenderer->WindowPos, sizeof(RECT)); + + if (pUnkOuter) + pVideoRenderer->outer_unk = pUnkOuter; + else + pVideoRenderer->outer_unk = &pVideoRenderer->IUnknown_inner; + + hr = BaseRenderer_Init(&pVideoRenderer->renderer, &VideoRenderer_Vtbl, pUnkOuter, + &CLSID_VideoRenderer, (DWORD_PTR)(__FILE__ ": VideoRendererImpl.csFilter"), + &BaseFuncTable); + + if (FAILED(hr)) + goto fail; + + hr = BaseControlWindow_Init(&pVideoRenderer->baseControlWindow, &IVideoWindow_VTable, + &pVideoRenderer->renderer.filter, &pVideoRenderer->renderer.filter.csFilter, + &pVideoRenderer->renderer.pInputPin->pin, &renderer_BaseWindowFuncTable); + if (FAILED(hr)) + goto fail; + + hr = BaseControlVideo_Init(&pVideoRenderer->baseControlVideo, &IBasicVideo_VTable, + &pVideoRenderer->renderer.filter, &pVideoRenderer->renderer.filter.csFilter, + &pVideoRenderer->renderer.pInputPin->pin, &renderer_BaseControlVideoFuncTable); + if (FAILED(hr)) + goto fail; + + if (!CreateRenderingSubsystem(pVideoRenderer)) { + hr = E_FAIL; + goto fail; + } + + *ppv = &pVideoRenderer->IUnknown_inner; + return S_OK; + +fail: + BaseRendererImpl_Release(&pVideoRenderer->renderer.filter.IBaseFilter_iface); + CoTaskMemFree(pVideoRenderer); + return hr; +} + +HRESULT VideoRendererDefault_create(IUnknown * pUnkOuter, LPVOID * ppv) +{ + /* TODO: Attempt to use the VMR-7 renderer instead when possible */ + return VideoRenderer_create(pUnkOuter, ppv); +} diff --git a/reactos/dll/directx/quartz/vmr9.c b/reactos/dll/directx/quartz/vmr9.c new file mode 100644 index 00000000000..5a837ddaf2c --- /dev/null +++ b/reactos/dll/directx/quartz/vmr9.c @@ -0,0 +1,2304 @@ +/* + * Video Mixing Renderer for dx9 + * + * Copyright 2004 Christian Costa + * Copyright 2008 Maarten Lankhorst + * Copyright 2012 Aric Stewart + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" + +#define NONAMELESSSTRUCT +#define NONAMELESSUNION +#include "quartz_private.h" + +#include "uuids.h" +#include "vfwmsgs.h" +#include "amvideo.h" +#include "windef.h" +#include "winbase.h" +#include "dshow.h" +#include "evcode.h" +#include "strmif.h" +#include "ddraw.h" +#include "dvdmedia.h" +#include "d3d9.h" +#include "vmr9.h" +#include "pin.h" + +#include "wine/unicode.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(quartz); + +typedef struct +{ + BaseRenderer renderer; + BaseControlWindow baseControlWindow; + BaseControlVideo baseControlVideo; + + IUnknown IUnknown_inner; + IAMFilterMiscFlags IAMFilterMiscFlags_iface; + IVMRFilterConfig9 IVMRFilterConfig9_iface; + IVMRWindowlessControl9 IVMRWindowlessControl9_iface; + IVMRSurfaceAllocatorNotify9 IVMRSurfaceAllocatorNotify9_iface; + + IVMRSurfaceAllocatorEx9 *allocator; + IVMRImagePresenter9 *presenter; + BOOL allocator_is_ex; + + /* + * The Video Mixing Renderer supports 3 modes, renderless, windowless and windowed + * What I do is implement windowless as a special case of renderless, and then + * windowed also as a special case of windowless. This is probably the easiest way. + */ + VMR9Mode mode; + BITMAPINFOHEADER bmiheader; + IUnknown * outer_unk; + BOOL bUnkOuterValid; + BOOL bAggregatable; + + HMODULE hD3d9; + + /* Presentation related members */ + IDirect3DDevice9 *allocator_d3d9_dev; + HMONITOR allocator_mon; + DWORD num_surfaces; + DWORD cur_surface; + DWORD_PTR cookie; + + /* for Windowless Mode */ + HWND hWndClippingWindow; + + RECT source_rect; + RECT target_rect; + LONG VideoWidth; + LONG VideoHeight; +} VMR9Impl; + +static inline VMR9Impl *impl_from_inner_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, VMR9Impl, IUnknown_inner); +} + +static inline VMR9Impl *impl_from_BaseWindow( BaseWindow *wnd ) +{ + return CONTAINING_RECORD(wnd, VMR9Impl, baseControlWindow.baseWindow); +} + +static inline VMR9Impl *impl_from_IVideoWindow( IVideoWindow *iface) +{ + return CONTAINING_RECORD(iface, VMR9Impl, baseControlWindow.IVideoWindow_iface); +} + +static inline VMR9Impl *impl_from_BaseControlVideo( BaseControlVideo *cvid ) +{ + return CONTAINING_RECORD(cvid, VMR9Impl, baseControlVideo); +} + +static inline VMR9Impl *impl_from_IBasicVideo( IBasicVideo *iface) +{ + return CONTAINING_RECORD(iface, VMR9Impl, baseControlVideo.IBasicVideo_iface); +} + +static inline VMR9Impl *impl_from_IAMFilterMiscFlags( IAMFilterMiscFlags *iface) +{ + return CONTAINING_RECORD(iface, VMR9Impl, IAMFilterMiscFlags_iface); +} + +static inline VMR9Impl *impl_from_IVMRFilterConfig9( IVMRFilterConfig9 *iface) +{ + return CONTAINING_RECORD(iface, VMR9Impl, IVMRFilterConfig9_iface); +} + +static inline VMR9Impl *impl_from_IVMRWindowlessControl9( IVMRWindowlessControl9 *iface) +{ + return CONTAINING_RECORD(iface, VMR9Impl, IVMRWindowlessControl9_iface); +} + +static inline VMR9Impl *impl_from_IVMRSurfaceAllocatorNotify9( IVMRSurfaceAllocatorNotify9 *iface) +{ + return CONTAINING_RECORD(iface, VMR9Impl, IVMRSurfaceAllocatorNotify9_iface); +} + +typedef struct +{ + IVMRImagePresenter9 IVMRImagePresenter9_iface; + IVMRSurfaceAllocatorEx9 IVMRSurfaceAllocatorEx9_iface; + + LONG refCount; + + HANDLE ack; + DWORD tid; + HANDLE hWndThread; + + IDirect3DDevice9 *d3d9_dev; + IDirect3D9 *d3d9_ptr; + IDirect3DSurface9 **d3d9_surfaces; + IDirect3DVertexBuffer9 *d3d9_vertex; + HMONITOR hMon; + DWORD num_surfaces; + + BOOL reset; + VMR9AllocationInfo info; + + VMR9Impl* pVMR9; + IVMRSurfaceAllocatorNotify9 *SurfaceAllocatorNotify; +} VMR9DefaultAllocatorPresenterImpl; + +static inline VMR9DefaultAllocatorPresenterImpl *impl_from_IVMRImagePresenter9( IVMRImagePresenter9 *iface) +{ + return CONTAINING_RECORD(iface, VMR9DefaultAllocatorPresenterImpl, IVMRImagePresenter9_iface); +} + +static inline VMR9DefaultAllocatorPresenterImpl *impl_from_IVMRSurfaceAllocatorEx9( IVMRSurfaceAllocatorEx9 *iface) +{ + return CONTAINING_RECORD(iface, VMR9DefaultAllocatorPresenterImpl, IVMRSurfaceAllocatorEx9_iface); +} + +static HRESULT VMR9DefaultAllocatorPresenterImpl_create(VMR9Impl *parent, LPVOID * ppv); + +static DWORD VMR9_SendSampleData(VMR9Impl *This, VMR9PresentationInfo *info, LPBYTE data, DWORD size) +{ + AM_MEDIA_TYPE *amt; + HRESULT hr = S_OK; + int width; + int height; + BITMAPINFOHEADER *bmiHeader; + D3DLOCKED_RECT lock; + + TRACE("%p %p %d\n", This, data, size); + + amt = &This->renderer.pInputPin->pin.mtCurrent; + + if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo)) + { + bmiHeader = &((VIDEOINFOHEADER *)amt->pbFormat)->bmiHeader; + } + else if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo2)) + { + bmiHeader = &((VIDEOINFOHEADER2 *)amt->pbFormat)->bmiHeader; + } + else + { + FIXME("Unknown type %s\n", debugstr_guid(&amt->subtype)); + return VFW_E_RUNTIME_ERROR; + } + + TRACE("biSize = %d\n", bmiHeader->biSize); + TRACE("biWidth = %d\n", bmiHeader->biWidth); + TRACE("biHeight = %d\n", bmiHeader->biHeight); + TRACE("biPlanes = %d\n", bmiHeader->biPlanes); + TRACE("biBitCount = %d\n", bmiHeader->biBitCount); + TRACE("biCompression = %s\n", debugstr_an((LPSTR)&(bmiHeader->biCompression), 4)); + TRACE("biSizeImage = %d\n", bmiHeader->biSizeImage); + + width = bmiHeader->biWidth; + height = bmiHeader->biHeight; + + TRACE("Src Rect: %d %d %d %d\n", This->source_rect.left, This->source_rect.top, This->source_rect.right, This->source_rect.bottom); + TRACE("Dst Rect: %d %d %d %d\n", This->target_rect.left, This->target_rect.top, This->target_rect.right, This->target_rect.bottom); + + hr = IDirect3DSurface9_LockRect(info->lpSurf, &lock, NULL, D3DLOCK_DISCARD); + if (FAILED(hr)) + { + ERR("IDirect3DSurface9_LockRect failed (%x)\n",hr); + return hr; + } + + if (lock.Pitch != width * bmiHeader->biBitCount / 8) + { + WARN("Slow path! %u/%u\n", lock.Pitch, width * bmiHeader->biBitCount/8); + + while (height--) + { + memcpy(lock.pBits, data, width * bmiHeader->biBitCount / 8); + data = data + width * bmiHeader->biBitCount / 8; + lock.pBits = (char *)lock.pBits + lock.Pitch; + } + } + else memcpy(lock.pBits, data, size); + + IDirect3DSurface9_UnlockRect(info->lpSurf); + + hr = IVMRImagePresenter9_PresentImage(This->presenter, This->cookie, info); + return hr; +} + +static HRESULT WINAPI VMR9_DoRenderSample(BaseRenderer *iface, IMediaSample * pSample) +{ + VMR9Impl *This = (VMR9Impl *)iface; + LPBYTE pbSrcStream = NULL; + long cbSrcStream = 0; + REFERENCE_TIME tStart, tStop; + VMR9PresentationInfo info; + HRESULT hr; + + TRACE("%p %p\n", iface, pSample); + + /* It is possible that there is no device at this point */ + + if (!This->allocator || !This->presenter) + { + ERR("NO PRESENTER!!\n"); + return S_FALSE; + } + + hr = IMediaSample_GetTime(pSample, &tStart, &tStop); + if (FAILED(hr)) + info.dwFlags = VMR9Sample_SrcDstRectsValid; + else + info.dwFlags = VMR9Sample_SrcDstRectsValid | VMR9Sample_TimeValid; + + if (IMediaSample_IsDiscontinuity(pSample) == S_OK) + info.dwFlags |= VMR9Sample_Discontinuity; + + if (IMediaSample_IsPreroll(pSample) == S_OK) + info.dwFlags |= VMR9Sample_Preroll; + + if (IMediaSample_IsSyncPoint(pSample) == S_OK) + info.dwFlags |= VMR9Sample_SyncPoint; + + /* If we render ourselves, and this is a preroll sample, discard it */ + if (This->baseControlWindow.baseWindow.hWnd && (info.dwFlags & VMR9Sample_Preroll)) + { + return S_OK; + } + + hr = IMediaSample_GetPointer(pSample, &pbSrcStream); + if (FAILED(hr)) + { + ERR("Cannot get pointer to sample data (%x)\n", hr); + return hr; + } + + cbSrcStream = IMediaSample_GetActualDataLength(pSample); + + info.rtStart = tStart; + info.rtEnd = tStop; + info.szAspectRatio.cx = This->bmiheader.biWidth; + info.szAspectRatio.cy = This->bmiheader.biHeight; + + hr = IVMRSurfaceAllocatorEx9_GetSurface(This->allocator, This->cookie, (++This->cur_surface)%This->num_surfaces, 0, &info.lpSurf); + + if (FAILED(hr)) + return hr; + + VMR9_SendSampleData(This, &info, pbSrcStream, cbSrcStream); + IDirect3DSurface9_Release(info.lpSurf); + + return hr; +} + +static HRESULT WINAPI VMR9_CheckMediaType(BaseRenderer *iface, const AM_MEDIA_TYPE * pmt) +{ + VMR9Impl *This = (VMR9Impl*)iface; + + if (!IsEqualIID(&pmt->majortype, &MEDIATYPE_Video) || !pmt->pbFormat) + return S_FALSE; + + /* Ignore subtype, test for bicompression instead */ + if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) + { + VIDEOINFOHEADER *format = (VIDEOINFOHEADER *)pmt->pbFormat; + + This->bmiheader = format->bmiHeader; + TRACE("Resolution: %dx%d\n", format->bmiHeader.biWidth, format->bmiHeader.biHeight); + This->source_rect.right = This->VideoWidth = format->bmiHeader.biWidth; + This->source_rect.bottom = This->VideoHeight = format->bmiHeader.biHeight; + This->source_rect.top = This->source_rect.left = 0; + } + else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2)) + { + VIDEOINFOHEADER2 *format = (VIDEOINFOHEADER2 *)pmt->pbFormat; + + This->bmiheader = format->bmiHeader; + + TRACE("Resolution: %dx%d\n", format->bmiHeader.biWidth, format->bmiHeader.biHeight); + This->source_rect.right = This->VideoWidth = format->bmiHeader.biWidth; + This->source_rect.bottom = This->VideoHeight = format->bmiHeader.biHeight; + This->source_rect.top = This->source_rect.left = 0; + } + else + { + ERR("Format type %s not supported\n", debugstr_guid(&pmt->formattype)); + return S_FALSE; + } + if (This->bmiheader.biCompression) + return S_FALSE; + return S_OK; +} + +static HRESULT VMR9_maybe_init(VMR9Impl *This, BOOL force) +{ + VMR9AllocationInfo info; + DWORD buffers; + HRESULT hr; + + TRACE("my mode: %u, my window: %p, my last window: %p\n", This->mode, This->baseControlWindow.baseWindow.hWnd, This->hWndClippingWindow); + if (This->baseControlWindow.baseWindow.hWnd || !This->renderer.pInputPin->pin.pConnectedTo) + return S_OK; + + if (This->mode == VMR9Mode_Windowless && !This->hWndClippingWindow) + return (force ? VFW_E_RUNTIME_ERROR : S_OK); + + TRACE("Initializing\n"); + info.dwFlags = VMR9AllocFlag_TextureSurface; + info.dwHeight = This->source_rect.bottom; + info.dwWidth = This->source_rect.right; + info.Pool = D3DPOOL_DEFAULT; + info.MinBuffers = 2; + FIXME("Reduce ratio to least common denominator\n"); + info.szAspectRatio.cx = info.dwWidth; + info.szAspectRatio.cy = info.dwHeight; + info.szNativeSize.cx = This->bmiheader.biWidth; + info.szNativeSize.cy = This->bmiheader.biHeight; + buffers = 2; + + switch (This->bmiheader.biBitCount) + { + case 8: info.Format = D3DFMT_R3G3B2; break; + case 15: info.Format = D3DFMT_X1R5G5B5; break; + case 16: info.Format = D3DFMT_R5G6B5; break; + case 24: info.Format = D3DFMT_R8G8B8; break; + case 32: info.Format = D3DFMT_X8R8G8B8; break; + default: + FIXME("Unknown bpp %u\n", This->bmiheader.biBitCount); + hr = E_INVALIDARG; + } + + This->cur_surface = 0; + if (This->num_surfaces) + { + ERR("num_surfaces or d3d9_surfaces not 0\n"); + return E_FAIL; + } + + hr = IVMRSurfaceAllocatorEx9_InitializeDevice(This->allocator, This->cookie, &info, &buffers); + if (SUCCEEDED(hr)) + { + This->source_rect.left = This->source_rect.top = 0; + This->source_rect.right = This->bmiheader.biWidth; + This->source_rect.bottom = This->bmiheader.biHeight; + + This->num_surfaces = buffers; + } + return hr; +} + +static VOID WINAPI VMR9_OnStartStreaming(BaseRenderer* iface) +{ + VMR9Impl *This = (VMR9Impl*)iface; + + TRACE("(%p)\n", This); + + VMR9_maybe_init(This, TRUE); + IVMRImagePresenter9_StartPresenting(This->presenter, This->cookie); + SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL, + This->source_rect.left, + This->source_rect.top, + This->source_rect.right - This->source_rect.left, + This->source_rect.bottom - This->source_rect.top, + SWP_NOZORDER|SWP_NOMOVE|SWP_DEFERERASE); + ShowWindow(This->baseControlWindow.baseWindow.hWnd, SW_SHOW); + GetClientRect(This->baseControlWindow.baseWindow.hWnd, &This->target_rect); +} + +static VOID WINAPI VMR9_OnStopStreaming(BaseRenderer* iface) +{ + VMR9Impl *This = (VMR9Impl*)iface; + + TRACE("(%p)\n", This); + + if (This->renderer.filter.state == State_Running) + IVMRImagePresenter9_StopPresenting(This->presenter, This->cookie); +} + +static HRESULT WINAPI VMR9_ShouldDrawSampleNow(BaseRenderer *This, IMediaSample *pSample, REFERENCE_TIME *pStartTime, REFERENCE_TIME *pEndTime) +{ + /* Preroll means the sample isn't shown, this is used for key frames and things like that */ + if (IMediaSample_IsPreroll(pSample) == S_OK) + return E_FAIL; + return S_FALSE; +} + +static HRESULT WINAPI VMR9_CompleteConnect(BaseRenderer *This, IPin *pReceivePin) +{ + VMR9Impl *pVMR9 = (VMR9Impl*)This; + HRESULT hr = S_OK; + + TRACE("(%p)\n", This); + + if (!pVMR9->mode && SUCCEEDED(hr)) + hr = IVMRFilterConfig9_SetRenderingMode(&pVMR9->IVMRFilterConfig9_iface, VMR9Mode_Windowed); + + if (SUCCEEDED(hr)) + hr = VMR9_maybe_init(pVMR9, FALSE); + + return hr; +} + +static HRESULT WINAPI VMR9_BreakConnect(BaseRenderer *This) +{ + VMR9Impl *pVMR9 = (VMR9Impl*)This; + HRESULT hr = S_OK; + + if (!pVMR9->mode) + return S_FALSE; + if (This->pInputPin->pin.pConnectedTo && pVMR9->allocator && pVMR9->presenter) + { + if (pVMR9->renderer.filter.state != State_Stopped) + { + ERR("Disconnecting while not stopped! UNTESTED!!\n"); + } + if (pVMR9->renderer.filter.state == State_Running) + hr = IVMRImagePresenter9_StopPresenting(pVMR9->presenter, pVMR9->cookie); + IVMRSurfaceAllocatorEx9_TerminateDevice(pVMR9->allocator, pVMR9->cookie); + pVMR9->num_surfaces = 0; + } + return hr; +} + +static const BaseRendererFuncTable BaseFuncTable = { + VMR9_CheckMediaType, + VMR9_DoRenderSample, + /**/ + NULL, + NULL, + NULL, + VMR9_OnStartStreaming, + VMR9_OnStopStreaming, + NULL, + NULL, + NULL, + VMR9_ShouldDrawSampleNow, + NULL, + /**/ + VMR9_CompleteConnect, + VMR9_BreakConnect, + NULL, + NULL, + NULL, +}; + +static LPWSTR WINAPI VMR9_GetClassWindowStyles(BaseWindow *This, DWORD *pClassStyles, DWORD *pWindowStyles, DWORD *pWindowStylesEx) +{ + static WCHAR classnameW[] = { 'I','V','M','R','9',' ','C','l','a','s','s', 0 }; + + *pClassStyles = 0; + *pWindowStyles = WS_SIZEBOX; + *pWindowStylesEx = 0; + + return classnameW; +} + +static RECT WINAPI VMR9_GetDefaultRect(BaseWindow *This) +{ + VMR9Impl* pVMR9 = impl_from_BaseWindow(This); + static RECT defRect; + + defRect.left = defRect.top = 0; + defRect.right = pVMR9->VideoWidth; + defRect.bottom = pVMR9->VideoHeight; + + return defRect; +} + +static BOOL WINAPI VMR9_OnSize(BaseWindow *This, LONG Width, LONG Height) +{ + VMR9Impl* pVMR9 = impl_from_BaseWindow(This); + + TRACE("WM_SIZE %d %d\n", Width, Height); + GetClientRect(This->hWnd, &pVMR9->target_rect); + TRACE("WM_SIZING: DestRect=(%d,%d),(%d,%d)\n", + pVMR9->target_rect.left, + pVMR9->target_rect.top, + pVMR9->target_rect.right - pVMR9->target_rect.left, + pVMR9->target_rect.bottom - pVMR9->target_rect.top); + return BaseWindowImpl_OnSize(This, Width, Height); +} + +static const BaseWindowFuncTable renderer_BaseWindowFuncTable = { + VMR9_GetClassWindowStyles, + VMR9_GetDefaultRect, + NULL, + BaseControlWindowImpl_PossiblyEatMessage, + VMR9_OnSize, +}; + +static HRESULT WINAPI VMR9_GetSourceRect(BaseControlVideo* This, RECT *pSourceRect) +{ + VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This); + CopyRect(pSourceRect,&pVMR9->source_rect); + return S_OK; +} + +static HRESULT WINAPI VMR9_GetStaticImage(BaseControlVideo* This, LONG *pBufferSize, LONG *pDIBImage) +{ + VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This); + BITMAPINFOHEADER *bmiHeader; + LONG needed_size; + AM_MEDIA_TYPE *amt = &pVMR9->renderer.pInputPin->pin.mtCurrent; + char *ptr; + + FIXME("(%p/%p)->(%p, %p): partial stub\n", pVMR9, This, pBufferSize, pDIBImage); + + EnterCriticalSection(&pVMR9->renderer.filter.csFilter); + + if (!pVMR9->renderer.pMediaSample) + { + LeaveCriticalSection(&pVMR9->renderer.filter.csFilter); + return (pVMR9->renderer.filter.state == State_Paused ? E_UNEXPECTED : VFW_E_NOT_PAUSED); + } + + if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo)) + { + bmiHeader = &((VIDEOINFOHEADER *)amt->pbFormat)->bmiHeader; + } + else if (IsEqualIID(&amt->formattype, &FORMAT_VideoInfo2)) + { + bmiHeader = &((VIDEOINFOHEADER2 *)amt->pbFormat)->bmiHeader; + } + else + { + FIXME("Unknown type %s\n", debugstr_guid(&amt->subtype)); + LeaveCriticalSection(&pVMR9->renderer.filter.csFilter); + return VFW_E_RUNTIME_ERROR; + } + + needed_size = bmiHeader->biSize; + needed_size += IMediaSample_GetActualDataLength(pVMR9->renderer.pMediaSample); + + if (!pDIBImage) + { + *pBufferSize = needed_size; + LeaveCriticalSection(&pVMR9->renderer.filter.csFilter); + return S_OK; + } + + if (needed_size < *pBufferSize) + { + ERR("Buffer too small %u/%u\n", needed_size, *pBufferSize); + LeaveCriticalSection(&pVMR9->renderer.filter.csFilter); + return E_FAIL; + } + *pBufferSize = needed_size; + + memcpy(pDIBImage, bmiHeader, bmiHeader->biSize); + IMediaSample_GetPointer(pVMR9->renderer.pMediaSample, (BYTE **)&ptr); + memcpy((char *)pDIBImage + bmiHeader->biSize, ptr, IMediaSample_GetActualDataLength(pVMR9->renderer.pMediaSample)); + + LeaveCriticalSection(&pVMR9->renderer.filter.csFilter); + return S_OK; +} + +static HRESULT WINAPI VMR9_GetTargetRect(BaseControlVideo* This, RECT *pTargetRect) +{ + VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This); + CopyRect(pTargetRect,&pVMR9->target_rect); + return S_OK; +} + +static VIDEOINFOHEADER* WINAPI VMR9_GetVideoFormat(BaseControlVideo* This) +{ + VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This); + AM_MEDIA_TYPE *pmt; + + TRACE("(%p/%p)\n", pVMR9, This); + + pmt = &pVMR9->renderer.pInputPin->pin.mtCurrent; + if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)) { + return (VIDEOINFOHEADER*)pmt->pbFormat; + } else if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo2)) { + static VIDEOINFOHEADER vih; + VIDEOINFOHEADER2 *vih2 = (VIDEOINFOHEADER2*)pmt->pbFormat; + memcpy(&vih,vih2,sizeof(VIDEOINFOHEADER)); + memcpy(&vih.bmiHeader, &vih2->bmiHeader, sizeof(BITMAPINFOHEADER)); + return &vih; + } else { + ERR("Unknown format type %s\n", qzdebugstr_guid(&pmt->formattype)); + return NULL; + } +} + +static HRESULT WINAPI VMR9_IsDefaultSourceRect(BaseControlVideo* This) +{ + VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This); + FIXME("(%p/%p)->(): stub !!!\n", pVMR9, This); + + return S_OK; +} + +static HRESULT WINAPI VMR9_IsDefaultTargetRect(BaseControlVideo* This) +{ + VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This); + FIXME("(%p/%p)->(): stub !!!\n", pVMR9, This); + + return S_OK; +} + +static HRESULT WINAPI VMR9_SetDefaultSourceRect(BaseControlVideo* This) +{ + VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This); + + pVMR9->source_rect.left = 0; + pVMR9->source_rect.top = 0; + pVMR9->source_rect.right = pVMR9->VideoWidth; + pVMR9->source_rect.bottom = pVMR9->VideoHeight; + + return S_OK; +} + +static HRESULT WINAPI VMR9_SetDefaultTargetRect(BaseControlVideo* This) +{ + RECT rect; + VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This); + + if (!GetClientRect(pVMR9->baseControlWindow.baseWindow.hWnd, &rect)) + return E_FAIL; + + pVMR9->target_rect.left = 0; + pVMR9->target_rect.top = 0; + pVMR9->target_rect.right = rect.right; + pVMR9->target_rect.bottom = rect.bottom; + + return S_OK; +} + +static HRESULT WINAPI VMR9_SetSourceRect(BaseControlVideo* This, RECT *pSourceRect) +{ + VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This); + CopyRect(&pVMR9->source_rect,pSourceRect); + return S_OK; +} + +static HRESULT WINAPI VMR9_SetTargetRect(BaseControlVideo* This, RECT *pTargetRect) +{ + VMR9Impl* pVMR9 = impl_from_BaseControlVideo(This); + CopyRect(&pVMR9->target_rect,pTargetRect); + return S_OK; +} + +static const BaseControlVideoFuncTable renderer_BaseControlVideoFuncTable = { + VMR9_GetSourceRect, + VMR9_GetStaticImage, + VMR9_GetTargetRect, + VMR9_GetVideoFormat, + VMR9_IsDefaultSourceRect, + VMR9_IsDefaultTargetRect, + VMR9_SetDefaultSourceRect, + VMR9_SetDefaultTargetRect, + VMR9_SetSourceRect, + VMR9_SetTargetRect +}; + +static HRESULT WINAPI VMR9Inner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv) +{ + VMR9Impl *This = impl_from_inner_IUnknown(iface); + TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv); + + if (This->bAggregatable) + This->bUnkOuterValid = TRUE; + + *ppv = NULL; + + if (IsEqualIID(riid, &IID_IUnknown)) + *ppv = &This->IUnknown_inner; + else if (IsEqualIID(riid, &IID_IVideoWindow)) + *ppv = &This->baseControlWindow.IVideoWindow_iface; + else if (IsEqualIID(riid, &IID_IBasicVideo)) + *ppv = &This->baseControlVideo.IBasicVideo_iface; + else if (IsEqualIID(riid, &IID_IAMFilterMiscFlags)) + *ppv = &This->IAMFilterMiscFlags_iface; + else if (IsEqualIID(riid, &IID_IVMRFilterConfig9)) + *ppv = &This->IVMRFilterConfig9_iface; + else if (IsEqualIID(riid, &IID_IVMRWindowlessControl9) && This->mode == VMR9Mode_Windowless) + *ppv = &This->IVMRWindowlessControl9_iface; + else if (IsEqualIID(riid, &IID_IVMRSurfaceAllocatorNotify9) && This->mode == VMR9Mode_Renderless) + *ppv = &This->IVMRSurfaceAllocatorNotify9_iface; + else + { + HRESULT hr; + hr = BaseRendererImpl_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv); + if (SUCCEEDED(hr)) + return hr; + } + + if (*ppv) + { + IUnknown_AddRef((IUnknown *)(*ppv)); + return S_OK; + } + + else if (IsEqualIID(riid, &IID_IBasicVideo2)) + FIXME("No interface for IID_IBasicVideo2\n"); + else if (IsEqualIID(riid, &IID_IVMRWindowlessControl9)) + ; + else if (IsEqualIID(riid, &IID_IVMRSurfaceAllocatorNotify9)) + ; + else if (IsEqualIID(riid, &IID_IMediaPosition)) + FIXME("No interface for IID_IMediaPosition\n"); + else if (IsEqualIID(riid, &IID_IQualProp)) + FIXME("No interface for IID_IQualProp\n"); + else if (IsEqualIID(riid, &IID_IVMRAspectRatioControl9)) + FIXME("No interface for IID_IVMRAspectRatioControl9\n"); + else if (IsEqualIID(riid, &IID_IVMRDeinterlaceControl9)) + FIXME("No interface for IID_IVMRDeinterlaceControl9\n"); + else if (IsEqualIID(riid, &IID_IVMRMixerBitmap9)) + FIXME("No interface for IID_IVMRMixerBitmap9\n"); + else if (IsEqualIID(riid, &IID_IVMRMonitorConfig9)) + FIXME("No interface for IID_IVMRMonitorConfig9\n"); + else if (IsEqualIID(riid, &IID_IVMRMixerControl9)) + FIXME("No interface for IID_IVMRMixerControl9\n"); + else + FIXME("No interface for %s\n", debugstr_guid(riid)); + + return E_NOINTERFACE; +} + +static ULONG WINAPI VMR9Inner_AddRef(IUnknown * iface) +{ + VMR9Impl *This = impl_from_inner_IUnknown(iface); + ULONG refCount = BaseFilterImpl_AddRef(&This->renderer.filter.IBaseFilter_iface); + + TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1); + + return refCount; +} + +static ULONG WINAPI VMR9Inner_Release(IUnknown * iface) +{ + VMR9Impl *This = impl_from_inner_IUnknown(iface); + ULONG refCount = BaseRendererImpl_Release(&This->renderer.filter.IBaseFilter_iface); + + TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1); + + if (!refCount) + { + TRACE("Destroying\n"); + BaseControlWindow_Destroy(&This->baseControlWindow); + CloseHandle(This->hD3d9); + + if (This->allocator) + IVMRSurfaceAllocatorEx9_Release(This->allocator); + if (This->presenter) + IVMRImagePresenter9_Release(This->presenter); + + This->num_surfaces = 0; + if (This->allocator_d3d9_dev) + { + IDirect3DDevice9_Release(This->allocator_d3d9_dev); + This->allocator_d3d9_dev = NULL; + } + + CoTaskMemFree(This); + } + return refCount; +} + +static const IUnknownVtbl IInner_VTable = +{ + VMR9Inner_QueryInterface, + VMR9Inner_AddRef, + VMR9Inner_Release +}; + +static HRESULT WINAPI VMR9_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv) +{ + VMR9Impl *This = (VMR9Impl *)iface; + + if (This->bAggregatable) + This->bUnkOuterValid = TRUE; + + if (This->outer_unk) + { + if (This->bAggregatable) + return IUnknown_QueryInterface(This->outer_unk, riid, ppv); + + if (IsEqualIID(riid, &IID_IUnknown)) + { + HRESULT hr; + + IUnknown_AddRef(&This->IUnknown_inner); + hr = IUnknown_QueryInterface(&This->IUnknown_inner, riid, ppv); + IUnknown_Release(&This->IUnknown_inner); + This->bAggregatable = TRUE; + return hr; + } + + *ppv = NULL; + return E_NOINTERFACE; + } + + return IUnknown_QueryInterface(&This->IUnknown_inner, riid, ppv); +} + +static ULONG WINAPI VMR9_AddRef(IBaseFilter * iface) +{ + VMR9Impl *This = (VMR9Impl *)iface; + LONG ret; + + if (This->outer_unk && This->bUnkOuterValid) + ret = IUnknown_AddRef(This->outer_unk); + else + ret = IUnknown_AddRef(&This->IUnknown_inner); + + TRACE("(%p)->AddRef from %d\n", iface, ret - 1); + + return ret; +} + +static ULONG WINAPI VMR9_Release(IBaseFilter * iface) +{ + VMR9Impl *This = (VMR9Impl *)iface; + LONG ret; + + if (This->outer_unk && This->bUnkOuterValid) + ret = IUnknown_Release(This->outer_unk); + else + ret = IUnknown_Release(&This->IUnknown_inner); + + TRACE("(%p)->Release from %d\n", iface, ret + 1); + + if (ret) + return ret; + return 0; +} + +static const IBaseFilterVtbl VMR9_Vtbl = +{ + VMR9_QueryInterface, + VMR9_AddRef, + VMR9_Release, + BaseFilterImpl_GetClassID, + BaseRendererImpl_Stop, + BaseRendererImpl_Pause, + BaseRendererImpl_Run, + BaseRendererImpl_GetState, + BaseRendererImpl_SetSyncSource, + BaseFilterImpl_GetSyncSource, + BaseFilterImpl_EnumPins, + BaseRendererImpl_FindPin, + BaseFilterImpl_QueryFilterInfo, + BaseFilterImpl_JoinFilterGraph, + BaseFilterImpl_QueryVendorInfo +}; + +/*** IUnknown methods ***/ +static HRESULT WINAPI Videowindow_QueryInterface(IVideoWindow *iface, REFIID riid, LPVOID*ppvObj) +{ + VMR9Impl *This = impl_from_IVideoWindow(iface); + + TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); + + return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppvObj); +} + +static ULONG WINAPI Videowindow_AddRef(IVideoWindow *iface) +{ + VMR9Impl *This = impl_from_IVideoWindow(iface); + + TRACE("(%p/%p)->()\n", This, iface); + + return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface); +} + +static ULONG WINAPI Videowindow_Release(IVideoWindow *iface) +{ + VMR9Impl *This = impl_from_IVideoWindow(iface); + + TRACE("(%p/%p)->()\n", This, iface); + + return VMR9_Release(&This->renderer.filter.IBaseFilter_iface); +} + +static const IVideoWindowVtbl IVideoWindow_VTable = +{ + Videowindow_QueryInterface, + Videowindow_AddRef, + Videowindow_Release, + BaseControlWindowImpl_GetTypeInfoCount, + BaseControlWindowImpl_GetTypeInfo, + BaseControlWindowImpl_GetIDsOfNames, + BaseControlWindowImpl_Invoke, + BaseControlWindowImpl_put_Caption, + BaseControlWindowImpl_get_Caption, + BaseControlWindowImpl_put_WindowStyle, + BaseControlWindowImpl_get_WindowStyle, + BaseControlWindowImpl_put_WindowStyleEx, + BaseControlWindowImpl_get_WindowStyleEx, + BaseControlWindowImpl_put_AutoShow, + BaseControlWindowImpl_get_AutoShow, + BaseControlWindowImpl_put_WindowState, + BaseControlWindowImpl_get_WindowState, + BaseControlWindowImpl_put_BackgroundPalette, + BaseControlWindowImpl_get_BackgroundPalette, + BaseControlWindowImpl_put_Visible, + BaseControlWindowImpl_get_Visible, + BaseControlWindowImpl_put_Left, + BaseControlWindowImpl_get_Left, + BaseControlWindowImpl_put_Width, + BaseControlWindowImpl_get_Width, + BaseControlWindowImpl_put_Top, + BaseControlWindowImpl_get_Top, + BaseControlWindowImpl_put_Height, + BaseControlWindowImpl_get_Height, + BaseControlWindowImpl_put_Owner, + BaseControlWindowImpl_get_Owner, + BaseControlWindowImpl_put_MessageDrain, + BaseControlWindowImpl_get_MessageDrain, + BaseControlWindowImpl_get_BorderColor, + BaseControlWindowImpl_put_BorderColor, + BaseControlWindowImpl_get_FullScreenMode, + BaseControlWindowImpl_put_FullScreenMode, + BaseControlWindowImpl_SetWindowForeground, + BaseControlWindowImpl_NotifyOwnerMessage, + BaseControlWindowImpl_SetWindowPosition, + BaseControlWindowImpl_GetWindowPosition, + BaseControlWindowImpl_GetMinIdealImageSize, + BaseControlWindowImpl_GetMaxIdealImageSize, + BaseControlWindowImpl_GetRestorePosition, + BaseControlWindowImpl_HideCursor, + BaseControlWindowImpl_IsCursorHidden +}; + +/*** IUnknown methods ***/ +static HRESULT WINAPI Basicvideo_QueryInterface(IBasicVideo *iface, REFIID riid, LPVOID * ppvObj) +{ + VMR9Impl *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); + + return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppvObj); +} + +static ULONG WINAPI Basicvideo_AddRef(IBasicVideo *iface) +{ + VMR9Impl *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->()\n", This, iface); + + return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface); +} + +static ULONG WINAPI Basicvideo_Release(IBasicVideo *iface) +{ + VMR9Impl *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->()\n", This, iface); + + return VMR9_Release(&This->renderer.filter.IBaseFilter_iface); +} + +static const IBasicVideoVtbl IBasicVideo_VTable = +{ + Basicvideo_QueryInterface, + Basicvideo_AddRef, + Basicvideo_Release, + BaseControlVideoImpl_GetTypeInfoCount, + BaseControlVideoImpl_GetTypeInfo, + BaseControlVideoImpl_GetIDsOfNames, + BaseControlVideoImpl_Invoke, + BaseControlVideoImpl_get_AvgTimePerFrame, + BaseControlVideoImpl_get_BitRate, + BaseControlVideoImpl_get_BitErrorRate, + BaseControlVideoImpl_get_VideoWidth, + BaseControlVideoImpl_get_VideoHeight, + BaseControlVideoImpl_put_SourceLeft, + BaseControlVideoImpl_get_SourceLeft, + BaseControlVideoImpl_put_SourceWidth, + BaseControlVideoImpl_get_SourceWidth, + BaseControlVideoImpl_put_SourceTop, + BaseControlVideoImpl_get_SourceTop, + BaseControlVideoImpl_put_SourceHeight, + BaseControlVideoImpl_get_SourceHeight, + BaseControlVideoImpl_put_DestinationLeft, + BaseControlVideoImpl_get_DestinationLeft, + BaseControlVideoImpl_put_DestinationWidth, + BaseControlVideoImpl_get_DestinationWidth, + BaseControlVideoImpl_put_DestinationTop, + BaseControlVideoImpl_get_DestinationTop, + BaseControlVideoImpl_put_DestinationHeight, + BaseControlVideoImpl_get_DestinationHeight, + BaseControlVideoImpl_SetSourcePosition, + BaseControlVideoImpl_GetSourcePosition, + BaseControlVideoImpl_SetDefaultSourcePosition, + BaseControlVideoImpl_SetDestinationPosition, + BaseControlVideoImpl_GetDestinationPosition, + BaseControlVideoImpl_SetDefaultDestinationPosition, + BaseControlVideoImpl_GetVideoSize, + BaseControlVideoImpl_GetVideoPaletteEntries, + BaseControlVideoImpl_GetCurrentImage, + BaseControlVideoImpl_IsUsingDefaultSource, + BaseControlVideoImpl_IsUsingDefaultDestination +}; + +static HRESULT WINAPI AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid, void **ppv) { + VMR9Impl *This = impl_from_IAMFilterMiscFlags(iface); + return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv); +} + +static ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface) { + VMR9Impl *This = impl_from_IAMFilterMiscFlags(iface); + return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface); +} + +static ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface) { + VMR9Impl *This = impl_from_IAMFilterMiscFlags(iface); + return VMR9_Release(&This->renderer.filter.IBaseFilter_iface); +} + +static ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface) { + return AM_FILTER_MISC_FLAGS_IS_RENDERER; +} + +static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = { + AMFilterMiscFlags_QueryInterface, + AMFilterMiscFlags_AddRef, + AMFilterMiscFlags_Release, + AMFilterMiscFlags_GetMiscFlags +}; + +static HRESULT WINAPI VMR9FilterConfig_QueryInterface(IVMRFilterConfig9 *iface, REFIID riid, LPVOID * ppv) +{ + VMR9Impl *This = impl_from_IVMRFilterConfig9(iface); + return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv); +} + +static ULONG WINAPI VMR9FilterConfig_AddRef(IVMRFilterConfig9 *iface) +{ + VMR9Impl *This = impl_from_IVMRFilterConfig9(iface); + return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface); +} + +static ULONG WINAPI VMR9FilterConfig_Release(IVMRFilterConfig9 *iface) +{ + VMR9Impl *This = impl_from_IVMRFilterConfig9(iface); + return VMR9_Release(&This->renderer.filter.IBaseFilter_iface); +} + +static HRESULT WINAPI VMR9FilterConfig_SetImageCompositor(IVMRFilterConfig9 *iface, IVMRImageCompositor9 *compositor) +{ + VMR9Impl *This = impl_from_IVMRFilterConfig9(iface); + + FIXME("(%p/%p)->(%p) stub\n", iface, This, compositor); + return E_NOTIMPL; +} + +static HRESULT WINAPI VMR9FilterConfig_SetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD max) +{ + VMR9Impl *This = impl_from_IVMRFilterConfig9(iface); + + FIXME("(%p/%p)->(%u) stub\n", iface, This, max); + return E_NOTIMPL; +} + +static HRESULT WINAPI VMR9FilterConfig_GetNumberOfStreams(IVMRFilterConfig9 *iface, DWORD *max) +{ + VMR9Impl *This = impl_from_IVMRFilterConfig9(iface); + + FIXME("(%p/%p)->(%p) stub\n", iface, This, max); + return E_NOTIMPL; +} + +static HRESULT WINAPI VMR9FilterConfig_SetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD renderflags) +{ + VMR9Impl *This = impl_from_IVMRFilterConfig9(iface); + + FIXME("(%p/%p)->(%u) stub\n", iface, This, renderflags); + return E_NOTIMPL; +} + +static HRESULT WINAPI VMR9FilterConfig_GetRenderingPrefs(IVMRFilterConfig9 *iface, DWORD *renderflags) +{ + VMR9Impl *This = impl_from_IVMRFilterConfig9(iface); + + FIXME("(%p/%p)->(%p) stub\n", iface, This, renderflags); + return E_NOTIMPL; +} + +static HRESULT WINAPI VMR9FilterConfig_SetRenderingMode(IVMRFilterConfig9 *iface, DWORD mode) +{ + HRESULT hr = S_OK; + VMR9Impl *This = impl_from_IVMRFilterConfig9(iface); + + TRACE("(%p/%p)->(%u)\n", iface, This, mode); + + EnterCriticalSection(&This->renderer.filter.csFilter); + if (This->mode) + { + LeaveCriticalSection(&This->renderer.filter.csFilter); + return VFW_E_WRONG_STATE; + } + + if (This->allocator) + IVMRSurfaceAllocatorEx9_Release(This->allocator); + if (This->presenter) + IVMRImagePresenter9_Release(This->presenter); + + This->allocator = NULL; + This->presenter = NULL; + + switch (mode) + { + case VMR9Mode_Windowed: + case VMR9Mode_Windowless: + This->allocator_is_ex = 0; + This->cookie = ~0; + + hr = VMR9DefaultAllocatorPresenterImpl_create(This, (LPVOID*)&This->presenter); + if (SUCCEEDED(hr)) + hr = IVMRImagePresenter9_QueryInterface(This->presenter, &IID_IVMRSurfaceAllocatorEx9, (LPVOID*)&This->allocator); + if (FAILED(hr)) + { + ERR("Unable to find Presenter interface\n"); + IVMRImagePresenter9_Release(This->presenter); + This->allocator = NULL; + This->presenter = NULL; + } + else + hr = IVMRSurfaceAllocatorEx9_AdviseNotify(This->allocator, &This->IVMRSurfaceAllocatorNotify9_iface); + break; + case VMR9Mode_Renderless: + break; + default: + LeaveCriticalSection(&This->renderer.filter.csFilter); + return E_INVALIDARG; + } + + This->mode = mode; + LeaveCriticalSection(&This->renderer.filter.csFilter); + return hr; +} + +static HRESULT WINAPI VMR9FilterConfig_GetRenderingMode(IVMRFilterConfig9 *iface, DWORD *mode) +{ + VMR9Impl *This = impl_from_IVMRFilterConfig9(iface); + + TRACE("(%p/%p)->(%p) stub\n", iface, This, mode); + if (!mode) + return E_POINTER; + + if (This->mode) + *mode = This->mode; + else + *mode = VMR9Mode_Windowed; + + return S_OK; +} + +static const IVMRFilterConfig9Vtbl VMR9_FilterConfig_Vtbl = +{ + VMR9FilterConfig_QueryInterface, + VMR9FilterConfig_AddRef, + VMR9FilterConfig_Release, + VMR9FilterConfig_SetImageCompositor, + VMR9FilterConfig_SetNumberOfStreams, + VMR9FilterConfig_GetNumberOfStreams, + VMR9FilterConfig_SetRenderingPrefs, + VMR9FilterConfig_GetRenderingPrefs, + VMR9FilterConfig_SetRenderingMode, + VMR9FilterConfig_GetRenderingMode +}; + +static HRESULT WINAPI VMR9WindowlessControl_QueryInterface(IVMRWindowlessControl9 *iface, REFIID riid, LPVOID * ppv) +{ + VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface); + return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv); +} + +static ULONG WINAPI VMR9WindowlessControl_AddRef(IVMRWindowlessControl9 *iface) +{ + VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface); + return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface); +} + +static ULONG WINAPI VMR9WindowlessControl_Release(IVMRWindowlessControl9 *iface) +{ + VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface); + return VMR9_Release(&This->renderer.filter.IBaseFilter_iface); +} + +static HRESULT WINAPI VMR9WindowlessControl_GetNativeVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height, LONG *arwidth, LONG *arheight) +{ + VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface); + TRACE("(%p/%p)->(%p, %p, %p, %p)\n", iface, This, width, height, arwidth, arheight); + + if (!width || !height || !arwidth || !arheight) + { + ERR("Got no pointer\n"); + return E_POINTER; + } + + *width = This->bmiheader.biWidth; + *height = This->bmiheader.biHeight; + *arwidth = This->bmiheader.biWidth; + *arheight = This->bmiheader.biHeight; + + return S_OK; +} + +static HRESULT WINAPI VMR9WindowlessControl_GetMinIdealVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height) +{ + VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface); + + FIXME("(%p/%p)->(...) stub\n", iface, This); + return E_NOTIMPL; +} + +static HRESULT WINAPI VMR9WindowlessControl_GetMaxIdealVideoSize(IVMRWindowlessControl9 *iface, LONG *width, LONG *height) +{ + VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface); + + FIXME("(%p/%p)->(...) stub\n", iface, This); + return E_NOTIMPL; +} + +static HRESULT WINAPI VMR9WindowlessControl_SetVideoPosition(IVMRWindowlessControl9 *iface, const RECT *source, const RECT *dest) +{ + VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface); + + TRACE("(%p/%p)->(%p, %p)\n", iface, This, source, dest); + + EnterCriticalSection(&This->renderer.filter.csFilter); + + if (source) + This->source_rect = *source; + if (dest) + { + This->target_rect = *dest; + if (This->baseControlWindow.baseWindow.hWnd) + { + FIXME("Output rectangle: starting at %dx%d, up to point %dx%d\n", dest->left, dest->top, dest->right, dest->bottom); + SetWindowPos(This->baseControlWindow.baseWindow.hWnd, NULL, dest->left, dest->top, dest->right - dest->left, + dest->bottom-dest->top, SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOOWNERZORDER|SWP_NOREDRAW); + } + } + + LeaveCriticalSection(&This->renderer.filter.csFilter); + + return S_OK; +} + +static HRESULT WINAPI VMR9WindowlessControl_GetVideoPosition(IVMRWindowlessControl9 *iface, RECT *source, RECT *dest) +{ + VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface); + + if (source) + *source = This->source_rect; + + if (dest) + *dest = This->target_rect; + + FIXME("(%p/%p)->(%p/%p) stub\n", iface, This, source, dest); + return S_OK; +} + +static HRESULT WINAPI VMR9WindowlessControl_GetAspectRatioMode(IVMRWindowlessControl9 *iface, DWORD *mode) +{ + VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface); + + FIXME("(%p/%p)->(...) stub\n", iface, This); + return E_NOTIMPL; +} + +static HRESULT WINAPI VMR9WindowlessControl_SetAspectRatioMode(IVMRWindowlessControl9 *iface, DWORD mode) +{ + VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface); + + FIXME("(%p/%p)->(...) stub\n", iface, This); + return E_NOTIMPL; +} + +static HRESULT WINAPI VMR9WindowlessControl_SetVideoClippingWindow(IVMRWindowlessControl9 *iface, HWND hwnd) +{ + VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface); + + TRACE("(%p/%p)->(%p)\n", iface, This, hwnd); + + EnterCriticalSection(&This->renderer.filter.csFilter); + This->hWndClippingWindow = hwnd; + VMR9_maybe_init(This, FALSE); + if (!hwnd) + IVMRSurfaceAllocatorEx9_TerminateDevice(This->allocator, This->cookie); + LeaveCriticalSection(&This->renderer.filter.csFilter); + return S_OK; +} + +static HRESULT WINAPI VMR9WindowlessControl_RepaintVideo(IVMRWindowlessControl9 *iface, HWND hwnd, HDC hdc) +{ + VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface); + HRESULT hr; + + FIXME("(%p/%p)->(...) semi-stub\n", iface, This); + + EnterCriticalSection(&This->renderer.filter.csFilter); + if (hwnd != This->hWndClippingWindow && hwnd != This->baseControlWindow.baseWindow.hWnd) + { + ERR("Not handling changing windows yet!!!\n"); + LeaveCriticalSection(&This->renderer.filter.csFilter); + return S_OK; + } + + if (!This->allocator_d3d9_dev) + { + ERR("No d3d9 device!\n"); + LeaveCriticalSection(&This->renderer.filter.csFilter); + return VFW_E_WRONG_STATE; + } + + /* Windowless extension */ + hr = IDirect3DDevice9_Present(This->allocator_d3d9_dev, NULL, NULL, This->baseControlWindow.baseWindow.hWnd, NULL); + LeaveCriticalSection(&This->renderer.filter.csFilter); + + return hr; +} + +static HRESULT WINAPI VMR9WindowlessControl_DisplayModeChanged(IVMRWindowlessControl9 *iface) +{ + VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface); + + FIXME("(%p/%p)->(...) stub\n", iface, This); + return E_NOTIMPL; +} + +static HRESULT WINAPI VMR9WindowlessControl_GetCurrentImage(IVMRWindowlessControl9 *iface, BYTE **dib) +{ + VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface); + + FIXME("(%p/%p)->(...) stub\n", iface, This); + return E_NOTIMPL; +} + +static HRESULT WINAPI VMR9WindowlessControl_SetBorderColor(IVMRWindowlessControl9 *iface, COLORREF color) +{ + VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface); + + FIXME("(%p/%p)->(...) stub\n", iface, This); + return E_NOTIMPL; +} + +static HRESULT WINAPI VMR9WindowlessControl_GetBorderColor(IVMRWindowlessControl9 *iface, COLORREF *color) +{ + VMR9Impl *This = impl_from_IVMRWindowlessControl9(iface); + + FIXME("(%p/%p)->(...) stub\n", iface, This); + return E_NOTIMPL; +} + +static const IVMRWindowlessControl9Vtbl VMR9_WindowlessControl_Vtbl = +{ + VMR9WindowlessControl_QueryInterface, + VMR9WindowlessControl_AddRef, + VMR9WindowlessControl_Release, + VMR9WindowlessControl_GetNativeVideoSize, + VMR9WindowlessControl_GetMinIdealVideoSize, + VMR9WindowlessControl_GetMaxIdealVideoSize, + VMR9WindowlessControl_SetVideoPosition, + VMR9WindowlessControl_GetVideoPosition, + VMR9WindowlessControl_GetAspectRatioMode, + VMR9WindowlessControl_SetAspectRatioMode, + VMR9WindowlessControl_SetVideoClippingWindow, + VMR9WindowlessControl_RepaintVideo, + VMR9WindowlessControl_DisplayModeChanged, + VMR9WindowlessControl_GetCurrentImage, + VMR9WindowlessControl_SetBorderColor, + VMR9WindowlessControl_GetBorderColor +}; + +static HRESULT WINAPI VMR9SurfaceAllocatorNotify_QueryInterface(IVMRSurfaceAllocatorNotify9 *iface, REFIID riid, LPVOID * ppv) +{ + VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface); + return VMR9_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv); +} + +static ULONG WINAPI VMR9SurfaceAllocatorNotify_AddRef(IVMRSurfaceAllocatorNotify9 *iface) +{ + VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface); + return VMR9_AddRef(&This->renderer.filter.IBaseFilter_iface); +} + +static ULONG WINAPI VMR9SurfaceAllocatorNotify_Release(IVMRSurfaceAllocatorNotify9 *iface) +{ + VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface); + return VMR9_Release(&This->renderer.filter.IBaseFilter_iface); +} + +static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator(IVMRSurfaceAllocatorNotify9 *iface, DWORD_PTR id, IVMRSurfaceAllocator9 *alloc) +{ + VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface); + + /* FIXME: This code is not tested!!! */ + FIXME("(%p/%p)->(...) stub\n", iface, This); + This->cookie = id; + + if (This->presenter) + return VFW_E_WRONG_STATE; + + if (FAILED(IVMRSurfaceAllocator9_QueryInterface(alloc, &IID_IVMRImagePresenter9, (void **)&This->presenter))) + return E_NOINTERFACE; + + if (SUCCEEDED(IVMRSurfaceAllocator9_QueryInterface(alloc, &IID_IVMRSurfaceAllocatorEx9, (void **)&This->allocator))) + This->allocator_is_ex = 1; + else + { + This->allocator = (IVMRSurfaceAllocatorEx9 *)alloc; + IVMRSurfaceAllocator9_AddRef(alloc); + This->allocator_is_ex = 0; + } + + return S_OK; +} + +static HRESULT WINAPI VMR9SurfaceAllocatorNotify_SetD3DDevice(IVMRSurfaceAllocatorNotify9 *iface, IDirect3DDevice9 *device, HMONITOR monitor) +{ + VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface); + + FIXME("(%p/%p)->(...) semi-stub\n", iface, This); + if (This->allocator_d3d9_dev) + IDirect3DDevice9_Release(This->allocator_d3d9_dev); + This->allocator_d3d9_dev = device; + IDirect3DDevice9_AddRef(This->allocator_d3d9_dev); + This->allocator_mon = monitor; + + return S_OK; +} + +static HRESULT WINAPI VMR9SurfaceAllocatorNotify_ChangeD3DDevice(IVMRSurfaceAllocatorNotify9 *iface, IDirect3DDevice9 *device, HMONITOR monitor) +{ + VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface); + + FIXME("(%p/%p)->(...) semi-stub\n", iface, This); + if (This->allocator_d3d9_dev) + IDirect3DDevice9_Release(This->allocator_d3d9_dev); + This->allocator_d3d9_dev = device; + IDirect3DDevice9_AddRef(This->allocator_d3d9_dev); + This->allocator_mon = monitor; + + return S_OK; +} + +static HRESULT WINAPI VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper(IVMRSurfaceAllocatorNotify9 *iface, VMR9AllocationInfo *allocinfo, DWORD *numbuffers, IDirect3DSurface9 **surface) +{ + VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface); + DWORD i; + HRESULT hr = S_OK; + + FIXME("(%p/%p)->(%p, %p => %u, %p) semi-stub\n", iface, This, allocinfo, numbuffers, (numbuffers ? *numbuffers : 0), surface); + + if (!allocinfo || !numbuffers || !surface) + return E_POINTER; + + if (!*numbuffers || *numbuffers < allocinfo->MinBuffers) + { + ERR("Invalid number of buffers?\n"); + return E_INVALIDARG; + } + + if (!This->allocator_d3d9_dev) + { + ERR("No direct3d device when requested to allocate a surface!\n"); + return VFW_E_WRONG_STATE; + } + + if (allocinfo->dwFlags & VMR9AllocFlag_OffscreenSurface) + { + ERR("Creating offscreen surface\n"); + for (i = 0; i < *numbuffers; ++i) + { + hr = IDirect3DDevice9_CreateOffscreenPlainSurface(This->allocator_d3d9_dev, allocinfo->dwWidth, allocinfo->dwHeight, + allocinfo->Format, allocinfo->Pool, &surface[i], NULL); + if (FAILED(hr)) + break; + } + } + else if (allocinfo->dwFlags & VMR9AllocFlag_TextureSurface) + { + TRACE("Creating texture surface\n"); + for (i = 0; i < *numbuffers; ++i) + { + IDirect3DTexture9 *texture; + + hr = IDirect3DDevice9_CreateTexture(This->allocator_d3d9_dev, allocinfo->dwWidth, allocinfo->dwHeight, 1, 0, + allocinfo->Format, allocinfo->Pool, &texture, NULL); + if (FAILED(hr)) + break; + IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface[i]); + IDirect3DTexture9_Release(texture); + } + } + else + { + FIXME("Could not allocate for type %08x\n", allocinfo->dwFlags); + return E_NOTIMPL; + } + + if (i >= allocinfo->MinBuffers) + { + hr = S_OK; + *numbuffers = i; + } + else + { + for ( ; i > 0; --i) IDirect3DSurface9_Release(surface[i - 1]); + *numbuffers = 0; + } + return hr; +} + +static HRESULT WINAPI VMR9SurfaceAllocatorNotify_NotifyEvent(IVMRSurfaceAllocatorNotify9 *iface, LONG code, LONG_PTR param1, LONG_PTR param2) +{ + VMR9Impl *This = impl_from_IVMRSurfaceAllocatorNotify9(iface); + + FIXME("(%p/%p)->(...) stub\n", iface, This); + return E_NOTIMPL; +} + +static const IVMRSurfaceAllocatorNotify9Vtbl IVMRSurfaceAllocatorNotify9_Vtbl = +{ + VMR9SurfaceAllocatorNotify_QueryInterface, + VMR9SurfaceAllocatorNotify_AddRef, + VMR9SurfaceAllocatorNotify_Release, + VMR9SurfaceAllocatorNotify_AdviseSurfaceAllocator, + VMR9SurfaceAllocatorNotify_SetD3DDevice, + VMR9SurfaceAllocatorNotify_ChangeD3DDevice, + VMR9SurfaceAllocatorNotify_AllocateSurfaceHelper, + VMR9SurfaceAllocatorNotify_NotifyEvent +}; + +HRESULT VMR9Impl_create(IUnknown * outer_unk, LPVOID * ppv) +{ + HRESULT hr; + VMR9Impl * pVMR9; + + TRACE("(%p, %p)\n", outer_unk, ppv); + + *ppv = NULL; + + pVMR9 = CoTaskMemAlloc(sizeof(VMR9Impl)); + + pVMR9->hD3d9 = LoadLibraryA("d3d9.dll"); + if (!pVMR9->hD3d9 ) + { + WARN("Could not load d3d9.dll\n"); + CoTaskMemFree(pVMR9); + return VFW_E_DDRAW_CAPS_NOT_SUITABLE; + } + + pVMR9->outer_unk = outer_unk; + pVMR9->bUnkOuterValid = FALSE; + pVMR9->bAggregatable = FALSE; + pVMR9->IUnknown_inner.lpVtbl = &IInner_VTable; + pVMR9->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_Vtbl; + + pVMR9->mode = 0; + pVMR9->allocator_d3d9_dev = NULL; + pVMR9->allocator_mon= NULL; + pVMR9->num_surfaces = pVMR9->cur_surface = 0; + pVMR9->allocator = NULL; + pVMR9->presenter = NULL; + pVMR9->hWndClippingWindow = NULL; + pVMR9->IVMRFilterConfig9_iface.lpVtbl = &VMR9_FilterConfig_Vtbl; + pVMR9->IVMRWindowlessControl9_iface.lpVtbl = &VMR9_WindowlessControl_Vtbl; + pVMR9->IVMRSurfaceAllocatorNotify9_iface.lpVtbl = &IVMRSurfaceAllocatorNotify9_Vtbl; + + hr = BaseRenderer_Init(&pVMR9->renderer, &VMR9_Vtbl, outer_unk, &CLSID_VideoMixingRenderer9, (DWORD_PTR)(__FILE__ ": VMR9Impl.csFilter"), &BaseFuncTable); + if (FAILED(hr)) + goto fail; + + hr = BaseControlWindow_Init(&pVMR9->baseControlWindow, &IVideoWindow_VTable, &pVMR9->renderer.filter, &pVMR9->renderer.filter.csFilter, &pVMR9->renderer.pInputPin->pin, &renderer_BaseWindowFuncTable); + if (FAILED(hr)) + goto fail; + + hr = BaseControlVideo_Init(&pVMR9->baseControlVideo, &IBasicVideo_VTable, &pVMR9->renderer.filter, &pVMR9->renderer.filter.csFilter, &pVMR9->renderer.pInputPin->pin, &renderer_BaseControlVideoFuncTable); + if (FAILED(hr)) + goto fail; + + *ppv = (LPVOID)pVMR9; + ZeroMemory(&pVMR9->source_rect, sizeof(RECT)); + ZeroMemory(&pVMR9->target_rect, sizeof(RECT)); + TRACE("Created at %p\n", pVMR9); + return hr; + +fail: + BaseRendererImpl_Release(&pVMR9->renderer.filter.IBaseFilter_iface); + CloseHandle(pVMR9->hD3d9); + CoTaskMemFree(pVMR9); + return hr; +} + + + +static HRESULT WINAPI VMR9_ImagePresenter_QueryInterface(IVMRImagePresenter9 *iface, REFIID riid, LPVOID * ppv) +{ + VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface); + TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv); + + *ppv = NULL; + + if (IsEqualIID(riid, &IID_IUnknown)) + *ppv = (LPVOID)&(This->IVMRImagePresenter9_iface); + else if (IsEqualIID(riid, &IID_IVMRImagePresenter9)) + *ppv = &This->IVMRImagePresenter9_iface; + else if (IsEqualIID(riid, &IID_IVMRSurfaceAllocatorEx9)) + *ppv = &This->IVMRSurfaceAllocatorEx9_iface; + + if (*ppv) + { + IUnknown_AddRef((IUnknown *)(*ppv)); + return S_OK; + } + + FIXME("No interface for %s\n", debugstr_guid(riid)); + + return E_NOINTERFACE; +} + +static ULONG WINAPI VMR9_ImagePresenter_AddRef(IVMRImagePresenter9 *iface) +{ + VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface); + ULONG refCount = InterlockedIncrement(&This->refCount); + + TRACE("(%p)->() AddRef from %d\n", iface, refCount - 1); + + return refCount; +} + +static ULONG WINAPI VMR9_ImagePresenter_Release(IVMRImagePresenter9 *iface) +{ + VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface); + ULONG refCount = InterlockedDecrement(&This->refCount); + + TRACE("(%p)->() Release from %d\n", iface, refCount + 1); + + if (!refCount) + { + DWORD i; + TRACE("Destroying\n"); + CloseHandle(This->ack); + IDirect3D9_Release(This->d3d9_ptr); + + TRACE("Number of surfaces: %u\n", This->num_surfaces); + for (i = 0; i < This->num_surfaces; ++i) + { + IDirect3DSurface9 *surface = This->d3d9_surfaces[i]; + TRACE("Releasing surface %p\n", surface); + if (surface) + IDirect3DSurface9_Release(surface); + } + + CoTaskMemFree(This->d3d9_surfaces); + This->d3d9_surfaces = NULL; + This->num_surfaces = 0; + if (This->d3d9_vertex) + { + IDirect3DVertexBuffer9_Release(This->d3d9_vertex); + This->d3d9_vertex = NULL; + } + CoTaskMemFree(This); + return 0; + } + return refCount; +} + +static HRESULT WINAPI VMR9_ImagePresenter_StartPresenting(IVMRImagePresenter9 *iface, DWORD_PTR id) +{ + VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface); + + TRACE("(%p/%p/%p)->(...) stub\n", iface, This,This->pVMR9); + return S_OK; +} + +static HRESULT WINAPI VMR9_ImagePresenter_StopPresenting(IVMRImagePresenter9 *iface, DWORD_PTR id) +{ + VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface); + + TRACE("(%p/%p/%p)->(...) stub\n", iface, This,This->pVMR9); + return S_OK; +} + +#define USED_FVF (D3DFVF_XYZRHW | D3DFVF_TEX1) +struct VERTEX { float x, y, z, rhw, u, v; }; + +static HRESULT VMR9_ImagePresenter_PresentTexture(VMR9DefaultAllocatorPresenterImpl *This, IDirect3DSurface9 *surface) +{ + IDirect3DTexture9 *texture = NULL; + HRESULT hr; + + hr = IDirect3DDevice9_SetFVF(This->d3d9_dev, USED_FVF); + if (FAILED(hr)) + { + FIXME("SetFVF: %08x\n", hr); + return hr; + } + + hr = IDirect3DDevice9_SetStreamSource(This->d3d9_dev, 0, This->d3d9_vertex, 0, sizeof(struct VERTEX)); + if (FAILED(hr)) + { + FIXME("SetStreamSource: %08x\n", hr); + return hr; + } + + hr = IDirect3DSurface9_GetContainer(surface, &IID_IDirect3DTexture9, (void **) &texture); + if (FAILED(hr)) + { + FIXME("IDirect3DSurface9_GetContainer failed\n"); + return hr; + } + hr = IDirect3DDevice9_SetTexture(This->d3d9_dev, 0, (IDirect3DBaseTexture9 *)texture); + IDirect3DTexture9_Release(texture); + if (FAILED(hr)) + { + FIXME("SetTexture: %08x\n", hr); + return hr; + } + + hr = IDirect3DDevice9_DrawPrimitive(This->d3d9_dev, D3DPT_TRIANGLESTRIP, 0, 2); + if (FAILED(hr)) + { + FIXME("DrawPrimitive: %08x\n", hr); + return hr; + } + + return S_OK; +} + +static HRESULT VMR9_ImagePresenter_PresentOffscreenSurface(VMR9DefaultAllocatorPresenterImpl *This, IDirect3DSurface9 *surface) +{ + HRESULT hr; + IDirect3DSurface9 *target = NULL; + RECT target_rect; + + hr = IDirect3DDevice9_GetBackBuffer(This->d3d9_dev, 0, 0, D3DBACKBUFFER_TYPE_MONO, &target); + if (FAILED(hr)) + { + ERR("IDirect3DDevice9_GetBackBuffer -- %08x\n", hr); + return hr; + } + + target_rect = This->pVMR9->target_rect; + target_rect.right -= target_rect.left; + target_rect.bottom -= target_rect.top; + target_rect.left = target_rect.top = 0; + + /* Flip */ + target_rect.top = target_rect.bottom; + target_rect.bottom = 0; + + hr = IDirect3DDevice9_StretchRect(This->d3d9_dev, surface, &This->pVMR9->source_rect, target, &target_rect, D3DTEXF_LINEAR); + if (FAILED(hr)) + ERR("IDirect3DDevice9_StretchRect -- %08x\n", hr); + IDirect3DSurface9_Release(target); + + return hr; +} + +static HRESULT WINAPI VMR9_ImagePresenter_PresentImage(IVMRImagePresenter9 *iface, DWORD_PTR id, VMR9PresentationInfo *info) +{ + VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRImagePresenter9(iface); + HRESULT hr; + RECT output; + BOOL render = FALSE; + + TRACE("(%p/%p/%p)->(...) stub\n", iface, This, This->pVMR9); + GetWindowRect(This->pVMR9->baseControlWindow.baseWindow.hWnd, &output); + TRACE("Output rectangle: starting at %dx%d, up to point %dx%d\n", output.left, output.top, output.right, output.bottom); + + /* This might happen if we don't have active focus (eg on a different virtual desktop) */ + if (!This->d3d9_dev) + return S_OK; + + /* Display image here */ + hr = IDirect3DDevice9_Clear(This->d3d9_dev, 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); + if (FAILED(hr)) + FIXME("hr: %08x\n", hr); + hr = IDirect3DDevice9_BeginScene(This->d3d9_dev); + if (SUCCEEDED(hr)) + { + if (This->d3d9_vertex) + hr = VMR9_ImagePresenter_PresentTexture(This, info->lpSurf); + else + hr = VMR9_ImagePresenter_PresentOffscreenSurface(This, info->lpSurf); + render = SUCCEEDED(hr); + } + else + FIXME("BeginScene: %08x\n", hr); + hr = IDirect3DDevice9_EndScene(This->d3d9_dev); + if (render && SUCCEEDED(hr)) + { + hr = IDirect3DDevice9_Present(This->d3d9_dev, NULL, NULL, This->pVMR9->baseControlWindow.baseWindow.hWnd, NULL); + if (FAILED(hr)) + FIXME("Presenting image: %08x\n", hr); + } + + return S_OK; +} + +static const IVMRImagePresenter9Vtbl VMR9_ImagePresenter = +{ + VMR9_ImagePresenter_QueryInterface, + VMR9_ImagePresenter_AddRef, + VMR9_ImagePresenter_Release, + VMR9_ImagePresenter_StartPresenting, + VMR9_ImagePresenter_StopPresenting, + VMR9_ImagePresenter_PresentImage +}; + +static HRESULT WINAPI VMR9_SurfaceAllocator_QueryInterface(IVMRSurfaceAllocatorEx9 *iface, REFIID riid, LPVOID * ppv) +{ + VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface); + + return VMR9_ImagePresenter_QueryInterface(&This->IVMRImagePresenter9_iface, riid, ppv); +} + +static ULONG WINAPI VMR9_SurfaceAllocator_AddRef(IVMRSurfaceAllocatorEx9 *iface) +{ + VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface); + + return VMR9_ImagePresenter_AddRef(&This->IVMRImagePresenter9_iface); +} + +static ULONG WINAPI VMR9_SurfaceAllocator_Release(IVMRSurfaceAllocatorEx9 *iface) +{ + VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface); + + return VMR9_ImagePresenter_Release(&This->IVMRImagePresenter9_iface); +} + +static HRESULT VMR9_SurfaceAllocator_SetAllocationSettings(VMR9DefaultAllocatorPresenterImpl *This, VMR9AllocationInfo *allocinfo) +{ + D3DCAPS9 caps; + UINT width, height; + HRESULT hr; + + if (!(allocinfo->dwFlags & VMR9AllocFlag_TextureSurface)) + /* Only needed for texture surfaces */ + return S_OK; + + hr = IDirect3DDevice9_GetDeviceCaps(This->d3d9_dev, &caps); + if (FAILED(hr)) + return hr; + + if (!(caps.TextureCaps & D3DPTEXTURECAPS_POW2) || (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY)) + { + width = allocinfo->dwWidth; + height = allocinfo->dwHeight; + } + else + { + width = height = 1; + while (width < allocinfo->dwWidth) + width *= 2; + + while (height < allocinfo->dwHeight) + height *= 2; + FIXME("NPOW2 support missing, not using proper surfaces!\n"); + } + + if (caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY) + { + if (height > width) + width = height; + else + height = width; + FIXME("Square texture support required..\n"); + } + + hr = IDirect3DDevice9_CreateVertexBuffer(This->d3d9_dev, 4 * sizeof(struct VERTEX), D3DUSAGE_WRITEONLY, USED_FVF, allocinfo->Pool, &This->d3d9_vertex, NULL); + if (FAILED(hr)) + { + ERR("Couldn't create vertex buffer: %08x\n", hr); + return hr; + } + + This->reset = TRUE; + allocinfo->dwHeight = height; + allocinfo->dwWidth = width; + + return hr; +} + +static DWORD WINAPI MessageLoop(LPVOID lpParameter) +{ + MSG msg; + BOOL fGotMessage; + VMR9DefaultAllocatorPresenterImpl *This = lpParameter; + + TRACE("Starting message loop\n"); + + if (FAILED(BaseWindowImpl_PrepareWindow(&This->pVMR9->baseControlWindow.baseWindow))) + { + FIXME("Failed to prepare window\n"); + return FALSE; + } + + SetEvent(This->ack); + while ((fGotMessage = GetMessageW(&msg, NULL, 0, 0)) != 0 && fGotMessage != -1) + { + TranslateMessage(&msg); + DispatchMessageW(&msg); + } + + TRACE("End of message loop\n"); + + return 0; +} + +static UINT d3d9_adapter_from_hwnd(IDirect3D9 *d3d9, HWND hwnd, HMONITOR *mon_out) +{ + UINT d3d9_adapter; + HMONITOR mon; + + mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONULL); + if (!mon) + d3d9_adapter = 0; + else + { + for (d3d9_adapter = 0; d3d9_adapter < IDirect3D9_GetAdapterCount(d3d9); ++d3d9_adapter) + { + if (mon == IDirect3D9_GetAdapterMonitor(d3d9, d3d9_adapter)) + break; + } + if (d3d9_adapter >= IDirect3D9_GetAdapterCount(d3d9)) + d3d9_adapter = 0; + } + if (mon_out) + *mon_out = mon; + return d3d9_adapter; +} + +static BOOL CreateRenderingWindow(VMR9DefaultAllocatorPresenterImpl *This, VMR9AllocationInfo *info, DWORD *numbuffers) +{ + D3DPRESENT_PARAMETERS d3dpp; + DWORD d3d9_adapter; + HRESULT hr; + + TRACE("(%p)->()\n", This); + + This->hWndThread = CreateThread(NULL, 0, MessageLoop, This, 0, &This->tid); + if (!This->hWndThread) + return FALSE; + + WaitForSingleObject(This->ack, INFINITE); + + if (!This->pVMR9->baseControlWindow.baseWindow.hWnd) return FALSE; + + /* Obtain a monitor and d3d9 device */ + d3d9_adapter = d3d9_adapter_from_hwnd(This->d3d9_ptr, This->pVMR9->baseControlWindow.baseWindow.hWnd, &This->hMon); + + /* Now try to create the d3d9 device */ + ZeroMemory(&d3dpp, sizeof(d3dpp)); + d3dpp.Windowed = TRUE; + d3dpp.hDeviceWindow = This->pVMR9->baseControlWindow.baseWindow.hWnd; + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + d3dpp.BackBufferHeight = This->pVMR9->target_rect.bottom - This->pVMR9->target_rect.top; + d3dpp.BackBufferWidth = This->pVMR9->target_rect.right - This->pVMR9->target_rect.left; + + hr = IDirect3D9_CreateDevice(This->d3d9_ptr, d3d9_adapter, D3DDEVTYPE_HAL, NULL, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &This->d3d9_dev); + if (FAILED(hr)) + { + ERR("Could not create device: %08x\n", hr); + BaseWindowImpl_DoneWithWindow(&This->pVMR9->baseControlWindow.baseWindow); + return FALSE; + } + IVMRSurfaceAllocatorNotify9_SetD3DDevice(This->SurfaceAllocatorNotify, This->d3d9_dev, This->hMon); + + This->d3d9_surfaces = CoTaskMemAlloc(*numbuffers * sizeof(IDirect3DSurface9 *)); + ZeroMemory(This->d3d9_surfaces, *numbuffers * sizeof(IDirect3DSurface9 *)); + + hr = VMR9_SurfaceAllocator_SetAllocationSettings(This, info); + if (FAILED(hr)) + ERR("Setting allocation settings failed: %08x\n", hr); + + if (SUCCEEDED(hr)) + { + hr = IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(This->SurfaceAllocatorNotify, info, numbuffers, This->d3d9_surfaces); + if (FAILED(hr)) + ERR("Allocating surfaces failed: %08x\n", hr); + } + + if (FAILED(hr)) + { + IVMRSurfaceAllocatorEx9_TerminateDevice(This->pVMR9->allocator, This->pVMR9->cookie); + BaseWindowImpl_DoneWithWindow(&This->pVMR9->baseControlWindow.baseWindow); + return FALSE; + } + + This->num_surfaces = *numbuffers; + + return TRUE; +} + +static HRESULT WINAPI VMR9_SurfaceAllocator_InitializeDevice(IVMRSurfaceAllocatorEx9 *iface, DWORD_PTR id, VMR9AllocationInfo *allocinfo, DWORD *numbuffers) +{ + VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface); + + if (This->pVMR9->mode != VMR9Mode_Windowed && !This->pVMR9->hWndClippingWindow) + { + ERR("No window set\n"); + return VFW_E_WRONG_STATE; + } + + This->info = *allocinfo; + + if (!CreateRenderingWindow(This, allocinfo, numbuffers)) + { + ERR("Failed to create rendering window, expect no output!\n"); + return VFW_E_WRONG_STATE; + } + + return S_OK; +} + +static HRESULT WINAPI VMR9_SurfaceAllocator_TerminateDevice(IVMRSurfaceAllocatorEx9 *iface, DWORD_PTR id) +{ + VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface); + + if (!This->pVMR9->baseControlWindow.baseWindow.hWnd) + { + return S_OK; + } + + SendMessageW(This->pVMR9->baseControlWindow.baseWindow.hWnd, WM_CLOSE, 0, 0); + PostThreadMessageW(This->tid, WM_QUIT, 0, 0); + WaitForSingleObject(This->hWndThread, INFINITE); + This->hWndThread = NULL; + BaseWindowImpl_DoneWithWindow(&This->pVMR9->baseControlWindow.baseWindow); + + return S_OK; +} + +/* Recreate all surfaces (If allocated as D3DPOOL_DEFAULT) and survive! */ +static HRESULT VMR9_SurfaceAllocator_UpdateDeviceReset(VMR9DefaultAllocatorPresenterImpl *This) +{ + struct VERTEX t_vert[4]; + UINT width, height; + unsigned int i; + void *bits = NULL; + D3DPRESENT_PARAMETERS d3dpp; + HRESULT hr; + + if (!This->pVMR9->baseControlWindow.baseWindow.hWnd) + { + ERR("No window\n"); + return E_FAIL; + } + + if (!This->d3d9_surfaces || !This->reset) + return S_OK; + + This->reset = FALSE; + TRACE("RESETTING\n"); + if (This->d3d9_vertex) + { + IDirect3DVertexBuffer9_Release(This->d3d9_vertex); + This->d3d9_vertex = NULL; + } + + for (i = 0; i < This->num_surfaces; ++i) + { + IDirect3DSurface9 *surface = This->d3d9_surfaces[i]; + TRACE("Releasing surface %p\n", surface); + if (surface) + IDirect3DSurface9_Release(surface); + } + ZeroMemory(This->d3d9_surfaces, sizeof(IDirect3DSurface9 *) * This->num_surfaces); + + /* Now try to create the d3d9 device */ + ZeroMemory(&d3dpp, sizeof(d3dpp)); + d3dpp.Windowed = TRUE; + d3dpp.hDeviceWindow = This->pVMR9->baseControlWindow.baseWindow.hWnd; + d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; + + if (This->d3d9_dev) + IDirect3DDevice9_Release(This->d3d9_dev); + This->d3d9_dev = NULL; + hr = IDirect3D9_CreateDevice(This->d3d9_ptr, d3d9_adapter_from_hwnd(This->d3d9_ptr, This->pVMR9->baseControlWindow.baseWindow.hWnd, &This->hMon), D3DDEVTYPE_HAL, NULL, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &This->d3d9_dev); + if (FAILED(hr)) + { + hr = IDirect3D9_CreateDevice(This->d3d9_ptr, d3d9_adapter_from_hwnd(This->d3d9_ptr, This->pVMR9->baseControlWindow.baseWindow.hWnd, &This->hMon), D3DDEVTYPE_HAL, NULL, D3DCREATE_MIXED_VERTEXPROCESSING, &d3dpp, &This->d3d9_dev); + if (FAILED(hr)) + { + ERR("--> Creating device: %08x\n", hr); + return S_OK; + } + } + IVMRSurfaceAllocatorNotify9_ChangeD3DDevice(This->SurfaceAllocatorNotify, This->d3d9_dev, This->hMon); + + IVMRSurfaceAllocatorNotify9_AllocateSurfaceHelper(This->SurfaceAllocatorNotify, &This->info, &This->num_surfaces, This->d3d9_surfaces); + + This->reset = FALSE; + + if (!(This->info.dwFlags & VMR9AllocFlag_TextureSurface)) + return S_OK; + + hr = IDirect3DDevice9_CreateVertexBuffer(This->d3d9_dev, 4 * sizeof(struct VERTEX), D3DUSAGE_WRITEONLY, USED_FVF, + This->info.Pool, &This->d3d9_vertex, NULL); + + width = This->info.dwWidth; + height = This->info.dwHeight; + + for (i = 0; i < sizeof(t_vert) / sizeof(t_vert[0]); ++i) + { + if (i % 2) + { + t_vert[i].x = (float)This->pVMR9->target_rect.right - (float)This->pVMR9->target_rect.left - 0.5f; + t_vert[i].u = (float)This->pVMR9->source_rect.right / (float)width; + } + else + { + t_vert[i].x = -0.5f; + t_vert[i].u = (float)This->pVMR9->source_rect.left / (float)width; + } + + if (i % 4 < 2) + { + t_vert[i].y = -0.5f; + t_vert[i].v = (float)This->pVMR9->source_rect.bottom / (float)height; + } + else + { + t_vert[i].y = (float)This->pVMR9->target_rect.bottom - (float)This->pVMR9->target_rect.top - 0.5f; + t_vert[i].v = (float)This->pVMR9->source_rect.top / (float)height; + } + t_vert[i].z = 0.0f; + t_vert[i].rhw = 1.0f; + } + + FIXME("Vertex rectangle:\n"); + FIXME("X, Y: %f, %f\n", t_vert[0].x, t_vert[0].y); + FIXME("X, Y: %f, %f\n", t_vert[3].x, t_vert[3].y); + FIXME("TOP, LEFT: %f, %f\n", t_vert[0].u, t_vert[0].v); + FIXME("DOWN, BOTTOM: %f, %f\n", t_vert[3].u, t_vert[3].v); + + IDirect3DVertexBuffer9_Lock(This->d3d9_vertex, 0, sizeof(t_vert), &bits, 0); + memcpy(bits, t_vert, sizeof(t_vert)); + IDirect3DVertexBuffer9_Unlock(This->d3d9_vertex); + + return S_OK; +} + +static HRESULT WINAPI VMR9_SurfaceAllocator_GetSurface(IVMRSurfaceAllocatorEx9 *iface, DWORD_PTR id, DWORD surfaceindex, DWORD flags, IDirect3DSurface9 **surface) +{ + VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface); + + /* Update everything first, this is needed because the surface might be destroyed in the reset */ + if (!This->d3d9_dev) + { + TRACE("Device has left me!\n"); + return E_FAIL; + } + + VMR9_SurfaceAllocator_UpdateDeviceReset(This); + + if (surfaceindex >= This->num_surfaces) + { + ERR("surfaceindex is greater than num_surfaces\n"); + return E_FAIL; + } + *surface = This->d3d9_surfaces[surfaceindex]; + IDirect3DSurface9_AddRef(*surface); + + return S_OK; +} + +static HRESULT WINAPI VMR9_SurfaceAllocator_AdviseNotify(IVMRSurfaceAllocatorEx9 *iface, IVMRSurfaceAllocatorNotify9 *allocnotify) +{ + VMR9DefaultAllocatorPresenterImpl *This = impl_from_IVMRSurfaceAllocatorEx9(iface); + + TRACE("(%p/%p)->(...)\n", iface, This); + + /* No AddRef taken here or the base VMR9 filter would never be destroied */ + This->SurfaceAllocatorNotify = allocnotify; + return S_OK; +} + +static const IVMRSurfaceAllocatorEx9Vtbl VMR9_SurfaceAllocator = +{ + VMR9_SurfaceAllocator_QueryInterface, + VMR9_SurfaceAllocator_AddRef, + VMR9_SurfaceAllocator_Release, + VMR9_SurfaceAllocator_InitializeDevice, + VMR9_SurfaceAllocator_TerminateDevice, + VMR9_SurfaceAllocator_GetSurface, + VMR9_SurfaceAllocator_AdviseNotify, + NULL /* This isn't the SurfaceAllocatorEx type yet, working on it */ +}; + +static IDirect3D9 *init_d3d9(HMODULE d3d9_handle) +{ + IDirect3D9 * (__stdcall * d3d9_create)(UINT SDKVersion); + + d3d9_create = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9"); + if (!d3d9_create) return NULL; + + return d3d9_create(D3D_SDK_VERSION); +} + +static HRESULT VMR9DefaultAllocatorPresenterImpl_create(VMR9Impl *parent, LPVOID * ppv) +{ + HRESULT hr = S_OK; + int i; + VMR9DefaultAllocatorPresenterImpl* This; + + This = CoTaskMemAlloc(sizeof(VMR9DefaultAllocatorPresenterImpl)); + if (!This) + return E_OUTOFMEMORY; + + This->d3d9_ptr = init_d3d9(parent->hD3d9); + if (!This->d3d9_ptr) + { + WARN("Could not initialize d3d9.dll\n"); + CoTaskMemFree(This); + return VFW_E_DDRAW_CAPS_NOT_SUITABLE; + } + + i = 0; + do + { + D3DDISPLAYMODE mode; + + hr = IDirect3D9_EnumAdapterModes(This->d3d9_ptr, i++, D3DFMT_X8R8G8B8, 0, &mode); + } while (FAILED(hr)); + if (FAILED(hr)) + ERR("HR: %08x\n", hr); + if (hr == D3DERR_NOTAVAILABLE) + { + ERR("Format not supported\n"); + IDirect3D9_Release(This->d3d9_ptr); + CoTaskMemFree(This); + return VFW_E_DDRAW_CAPS_NOT_SUITABLE; + } + + This->IVMRImagePresenter9_iface.lpVtbl = &VMR9_ImagePresenter; + This->IVMRSurfaceAllocatorEx9_iface.lpVtbl = &VMR9_SurfaceAllocator; + + This->refCount = 1; + This->pVMR9 = parent; + This->d3d9_surfaces = NULL; + This->d3d9_dev = NULL; + This->hMon = 0; + This->d3d9_vertex = NULL; + This->num_surfaces = 0; + This->hWndThread = NULL; + This->ack = CreateEventW(NULL, 0, 0, NULL); + This->SurfaceAllocatorNotify = NULL; + This->reset = FALSE; + + *ppv = This; + return S_OK; +} diff --git a/reactos/dll/directx/quartz/waveparser.c b/reactos/dll/directx/quartz/waveparser.c index fed18e16637..f39a38a26d7 100644 --- a/reactos/dll/directx/quartz/waveparser.c +++ b/reactos/dll/directx/quartz/waveparser.c @@ -19,7 +19,6 @@ */ #include "quartz_private.h" -#include "control_private.h" #include "pin.h" //#include "uuids.h" @@ -49,6 +48,16 @@ typedef struct WAVEParserImpl DWORD dwLength; } WAVEParserImpl; +static inline WAVEParserImpl *impl_from_IMediaSeeking( IMediaSeeking *iface ) +{ + return CONTAINING_RECORD(iface, WAVEParserImpl, Parser.sourceSeeking.IMediaSeeking_iface); +} + +static inline WAVEParserImpl *impl_from_IBaseFilter( IBaseFilter *iface ) +{ + return CONTAINING_RECORD(iface, WAVEParserImpl, Parser.filter.IBaseFilter_iface); +} + static LONGLONG bytepos_to_duration(WAVEParserImpl *This, LONGLONG bytepos) { LONGLONG duration = BYTES_FROM_MEDIATIME(bytepos - This->StartOfFile); @@ -94,7 +103,7 @@ static HRESULT WAVEParser_Sample(LPVOID iface, IMediaSample * pSample, DWORD_PTR return S_OK; } - pOutputPin = (Parser_OutputPin *)This->Parser.ppPins[1]; + pOutputPin = unsafe_impl_Parser_OutputPin_from_IPin(This->Parser.ppPins[1]); if (SUCCEEDED(hr)) hr = IMemAllocator_GetBuffer(pin->pAlloc, &newsample, NULL, NULL, 0); @@ -132,7 +141,7 @@ static HRESULT WAVEParser_Sample(LPVOID iface, IMediaSample * pSample, DWORD_PTR IMediaSample_SetTime(pSample, &tAviStart, &tAviStop); - hr = OutputPin_SendSample(&pOutputPin->pin, pSample); + hr = BaseOutputPinImpl_Deliver(&pOutputPin->pin, pSample); if (hr != S_OK && hr != S_FALSE && hr != VFW_E_WRONG_STATE) ERR("Error sending sample (%x)\n", hr); else if (hr != S_OK) @@ -140,7 +149,7 @@ static HRESULT WAVEParser_Sample(LPVOID iface, IMediaSample * pSample, DWORD_PTR This->Parser.pInputPin->rtCurrent = tStart; } - if (tStop >= This->EndOfFile || (bytepos_to_duration(This, tStop) >= This->Parser.mediaSeeking.llStop) || hr == VFW_E_NOT_CONNECTED) + if (tStop >= This->EndOfFile || (bytepos_to_duration(This, tStop) >= This->Parser.sourceSeeking.llStop) || hr == VFW_E_NOT_CONNECTED) { unsigned int i; @@ -184,14 +193,14 @@ static HRESULT WAVEParser_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt) return S_FALSE; } -static HRESULT WAVEParserImpl_seek(IBaseFilter *iface) +static HRESULT WINAPI WAVEParserImpl_seek(IMediaSeeking *iface) { - WAVEParserImpl *This = (WAVEParserImpl *)iface; + WAVEParserImpl *This = impl_from_IMediaSeeking(iface); PullPin *pPin = This->Parser.pInputPin; IPin *victim = NULL; LONGLONG newpos, curpos, endpos, bytepos; - newpos = This->Parser.mediaSeeking.llCurrent; + newpos = This->Parser.sourceSeeking.llCurrent; curpos = bytepos_to_duration(This, pPin->rtCurrent); endpos = bytepos_to_duration(This, This->EndOfFile); bytepos = duration_to_bytepos(This, newpos); @@ -211,10 +220,10 @@ static HRESULT WAVEParserImpl_seek(IBaseFilter *iface) TRACE("Moving sound to %08u bytes!\n", (DWORD)BYTES_FROM_MEDIATIME(bytepos)); EnterCriticalSection(&pPin->thread_lock); - IPin_BeginFlush((IPin *)pPin); + IPin_BeginFlush(&pPin->pin.IPin_iface); /* Make sure this is done while stopped, BeginFlush takes care of this */ - EnterCriticalSection(&This->Parser.csFilter); + EnterCriticalSection(&This->Parser.filter.csFilter); IPin_ConnectedTo(This->Parser.ppPins[1], &victim); if (victim) { @@ -223,11 +232,11 @@ static HRESULT WAVEParserImpl_seek(IBaseFilter *iface) } pPin->rtStart = pPin->rtCurrent = bytepos; - ((Parser_OutputPin *)This->Parser.ppPins[1])->dwSamplesProcessed = 0; - LeaveCriticalSection(&This->Parser.csFilter); + unsafe_impl_Parser_OutputPin_from_IPin(This->Parser.ppPins[1])->dwSamplesProcessed = 0; + LeaveCriticalSection(&This->Parser.filter.csFilter); TRACE("Done flushing\n"); - IPin_EndFlush((IPin *)pPin); + IPin_EndFlush(&pPin->pin.IPin_iface); LeaveCriticalSection(&pPin->thread_lock); return S_OK; @@ -235,18 +244,18 @@ static HRESULT WAVEParserImpl_seek(IBaseFilter *iface) static HRESULT WAVEParser_InputPin_PreConnect(IPin * iface, IPin * pConnectPin, ALLOCATOR_PROPERTIES *props) { - PullPin *This = (PullPin *)iface; + PullPin *This = impl_PullPin_from_IPin(iface); HRESULT hr; RIFFLIST list; RIFFCHUNK chunk; LONGLONG pos = 0; /* in bytes */ PIN_INFO piOutput; AM_MEDIA_TYPE amt; - WAVEParserImpl * pWAVEParser = (WAVEParserImpl *)This->pin.pinInfo.pFilter; + WAVEParserImpl * pWAVEParser = impl_from_IBaseFilter(This->pin.pinInfo.pFilter); LONGLONG length, avail; piOutput.dir = PINDIR_OUTPUT; - piOutput.pFilter = (IBaseFilter *)This; + piOutput.pFilter = &pWAVEParser->Parser.filter.IBaseFilter_iface; lstrcpynW(piOutput.achName, wcsOutputPinName, sizeof(piOutput.achName) / sizeof(piOutput.achName[0])); hr = IAsyncReader_SyncRead(This->pReader, pos, sizeof(list), (BYTE *)&list); @@ -319,9 +328,9 @@ static HRESULT WAVEParser_InputPin_PreConnect(IPin * iface, IPin * pConnectPin, hr = Parser_AddPin(&(pWAVEParser->Parser), &piOutput, props, &amt); CoTaskMemFree(amt.pbFormat); - pWAVEParser->Parser.mediaSeeking.llCurrent = 0; - pWAVEParser->Parser.mediaSeeking.llStop = pWAVEParser->Parser.mediaSeeking.llDuration = bytepos_to_duration(pWAVEParser, pWAVEParser->EndOfFile); - TRACE("Duration: %u seconds\n", (DWORD)(pWAVEParser->Parser.mediaSeeking.llDuration / (LONGLONG)10000000)); + pWAVEParser->Parser.sourceSeeking.llCurrent = 0; + pWAVEParser->Parser.sourceSeeking.llStop = pWAVEParser->Parser.sourceSeeking.llDuration = bytepos_to_duration(pWAVEParser, pWAVEParser->EndOfFile); + TRACE("Duration: %u seconds\n", (DWORD)(pWAVEParser->Parser.sourceSeeking.llDuration / (LONGLONG)10000000)); This->rtStop = pWAVEParser->EndOfFile; This->rtStart = pWAVEParser->StartOfFile; @@ -362,7 +371,7 @@ static HRESULT WAVEParser_first_request(LPVOID iface) LONGLONG rtSampleStart = pin->rtNext; /* Add 4 for the next header, which should hopefully work */ LONGLONG rtSampleStop = rtSampleStart + MEDIATIME_FROM_BYTES(IMediaSample_GetSize(sample)); - Parser_OutputPin *outpin = (Parser_OutputPin *)This->Parser.ppPins[1]; + Parser_OutputPin *outpin = unsafe_impl_Parser_OutputPin_from_IPin(This->Parser.ppPins[1]); if (rtSampleStop > pin->rtStop) rtSampleStop = MEDIATIME_FROM_BYTES(ALIGNUP(BYTES_FROM_MEDIATIME(pin->rtStop), pin->cbAlign)); diff --git a/reactos/include/dxsdk/CMakeLists.txt b/reactos/include/dxsdk/CMakeLists.txt index 9a842b81c13..d079f26a9b3 100644 --- a/reactos/include/dxsdk/CMakeLists.txt +++ b/reactos/include/dxsdk/CMakeLists.txt @@ -19,7 +19,6 @@ list(APPEND SOURCE mmstream.idl qedit.idl regbag.idl - strmif.idl tvratings.idl vidcap.idl videoacc.idl diff --git a/reactos/include/dxsdk/axextend.idl b/reactos/include/dxsdk/axextend.idl index 72e37ce47c7..9b472019836 100644 --- a/reactos/include/dxsdk/axextend.idl +++ b/reactos/include/dxsdk/axextend.idl @@ -45,6 +45,7 @@ interface IAMVfwCompressDialogs; interface IAMVideoCompression; interface IAMVideoDecimationProperties; interface IAMVideoProcAmp; +interface IAMGraphBuilderCallback; interface ICaptureGraphBuilder; interface ICaptureGraphBuilder2; interface IConfigAviMux; @@ -235,14 +236,14 @@ typedef struct { ULONG cPins; [size_is(cPins)] const REGFILTERPINS *rgPins; - } DUMMYSTRUCTNAME; + } DUMMYSTRUCTNAME1; [case(2)] struct { ULONG cPins2; [size_is(cPins2)] const REGFILTERPINS2 *rgPins2; - } DUMMYSTRUCTNAME1; + } DUMMYSTRUCTNAME2; [default] ; @@ -1070,6 +1071,21 @@ interface IAMFilterMiscFlags : IUnknown ULONG GetMiscFlags(); }; +[ + local, + object, + uuid(4995f511-9ddb-4f12-bd3b-f04611807b79), + pointer_default(unique) +] +interface IAMGraphBuilderCallback : IUnknown +{ + HRESULT SelectedFilter( + [in] IMoniker *pMon); + + HRESULT CreatedFilter( + [in] IBaseFilter *pFil); +}; + [ local, object, diff --git a/reactos/include/psdk/control.idl b/reactos/include/psdk/control.idl index 7d1c83b92c3..884c4109b53 100644 --- a/reactos/include/psdk/control.idl +++ b/reactos/include/psdk/control.idl @@ -19,228 +19,230 @@ import "oaidl.idl"; -interface IMediaControl; -interface IBasicAudio; -interface IBasicVideo; -interface IVideoWindow; -interface IMediaEvent; -interface IMediaEventEx; -interface IMediaPosition; - -typedef LONG OAFilterState; -typedef LONG_PTR OAHWND; -typedef LONG_PTR OAEVENT; - -cpp_quote("#ifndef REFTIME_DEFINED") -cpp_quote("#define REFTIME_DEFINED") -typedef DOUBLE REFTIME; -cpp_quote("#endif") - -/***************************************************************************** - * IMediaControl interface - */ [ - object, - uuid(56a868b1-0ad4-11ce-b03a-0020af0ba770), - pointer_default(unique) + version(1.0), + uuid(56a868b0-0ad4-11ce-b03a-0020af0ba770) ] -interface IMediaControl : IDispatch +library QuartzTypeLib { - HRESULT Run(); - HRESULT Pause(); - HRESULT Stop(); - HRESULT GetState( [in] LONG msTimeout, [out] OAFilterState *pfs ); - HRESULT RenderFile( [in] BSTR strFilename ); - HRESULT AddSourceFilter( [in] BSTR strFilename, [out] IDispatch **ppUnk ); - [propget] HRESULT FilterCollection( [out] IDispatch **ppUnk ); - [propget] HRESULT RegFilterCollection( [out] IDispatch **ppUnk ); - HRESULT StopWhenReady(); -} + importlib("stdole2.tlb"); + + typedef LONG OAFilterState; + typedef LONG_PTR OAHWND; + typedef LONG_PTR OAEVENT; + + cpp_quote("#ifndef REFTIME_DEFINED") + cpp_quote("#define REFTIME_DEFINED") + typedef DOUBLE REFTIME; + cpp_quote("#endif") + + /*************************************************************************** + * IMediaControl interface + */ + [ + object, + uuid(56a868b1-0ad4-11ce-b03a-0020af0ba770), + pointer_default(unique) + ] + interface IMediaControl : IDispatch + { + HRESULT Run(); + HRESULT Pause(); + HRESULT Stop(); + HRESULT GetState( [in] LONG msTimeout, [out] OAFilterState *pfs ); + HRESULT RenderFile( [in] BSTR strFilename ); + HRESULT AddSourceFilter( [in] BSTR strFilename, [out] IDispatch **ppUnk ); + [propget] HRESULT FilterCollection( [out] IDispatch **ppUnk ); + [propget] HRESULT RegFilterCollection( [out] IDispatch **ppUnk ); + HRESULT StopWhenReady(); + } -/***************************************************************************** - * IBasicAudio interface - */ -[ - object, - uuid(56a868b3-0ad4-11ce-b03a-0020af0ba770), - pointer_default(unique) -] -interface IBasicAudio : IDispatch -{ - [propput] HRESULT Volume( [in] LONG lVolume ); - [propget] HRESULT Volume( [out] LONG *plVolume ); - [propput] HRESULT Balance( [in] LONG lBalance ); - [propget] HRESULT Balance( [out] LONG *plBalance ); -} + /*************************************************************************** + * IBasicAudio interface + */ + [ + object, + uuid(56a868b3-0ad4-11ce-b03a-0020af0ba770), + pointer_default(unique) + ] + interface IBasicAudio : IDispatch + { + [propput] HRESULT Volume( [in] LONG lVolume ); + [propget] HRESULT Volume( [out] LONG *plVolume ); + [propput] HRESULT Balance( [in] LONG lBalance ); + [propget] HRESULT Balance( [out] LONG *plBalance ); + } -/***************************************************************************** - * IVideoWindow interface - */ -[ - object, - uuid(56a868b4-0ad4-11ce-b03a-0020af0ba770), - pointer_default(unique) -] -interface IVideoWindow : IDispatch -{ - [propput] HRESULT Caption( [in] BSTR strCaption ); - [propget] HRESULT Caption( [out] BSTR *strCaption ); - [propput] HRESULT WindowStyle( [in] LONG WindowStyle ); - [propget] HRESULT WindowStyle( [out] LONG *WindowStyle ); - [propput] HRESULT WindowStyleEx( [in] LONG WindowStyleEx ); - [propget] HRESULT WindowStyleEx( [out] LONG *WindowStyleEx ); - [propput] HRESULT AutoShow( [in] LONG AutoShow ); - [propget] HRESULT AutoShow( [out] LONG *AutoShow ); - [propput] HRESULT WindowState( [in] LONG WindowState ); - [propget] HRESULT WindowState( [out] LONG *WindowState ); - [propput] HRESULT BackgroundPalette( [in] LONG BackgroundPalette ); - [propget] HRESULT BackgroundPalette( [out] LONG *pBackgroundPalette ); - [propput] HRESULT Visible( [in] LONG Visible ); - [propget] HRESULT Visible( [out] LONG *pVisible ); - [propput] HRESULT Left( [in] LONG Left ); - [propget] HRESULT Left( [out] LONG *pLeft ); - [propput] HRESULT Width( [in] LONG Width ); - [propget] HRESULT Width( [out] LONG *pWidth ); - [propput] HRESULT Top( [in] LONG Top ); - [propget] HRESULT Top( [out] LONG *pTop ); - [propput] HRESULT Height( [in] LONG Height ); - [propget] HRESULT Height( [out] LONG *pHeight ); - [propput] HRESULT Owner( [in] OAHWND Owner ); - [propget] HRESULT Owner( [out] OAHWND *Owner ); - [propput] HRESULT MessageDrain( [in] OAHWND Drain ); - [propget] HRESULT MessageDrain( [out] OAHWND *Drain ); - [propget] HRESULT BorderColor( [out] LONG *Color ); - [propput] HRESULT BorderColor( [in] LONG Color ); - [propget] HRESULT FullScreenMode( [out] LONG *FullScreenMode ); - [propput] HRESULT FullScreenMode( [in] LONG FullScreenMode ); - HRESULT SetWindowForeground( [in] LONG Focus ); - HRESULT NotifyOwnerMessage( [in] OAHWND hwnd, [in] LONG uMsg, [in] LONG_PTR wParam, [in] LONG_PTR lParam ); - HRESULT SetWindowPosition( [in] LONG Left, [in] LONG Top, [in] LONG Width, [in] LONG Height ); - HRESULT GetWindowPosition( [out] LONG *pLeft, [out] LONG *pTop, [out] LONG *pWidth, [out] LONG *pHeight ); - HRESULT GetMinIdealImageSize( [out] LONG *pWidth, [out] LONG *pHeight ); - HRESULT GetMaxIdealImageSize( [out] LONG *pWidth, [out] LONG *pHeight ); - HRESULT GetRestorePosition( [out] LONG *pLeft, [out] LONG *pTop, [out] LONG *pWidth, [out] LONG *pHeight ); - HRESULT HideCursor( [in] LONG HideCursor ); - HRESULT IsCursorHidden( [out] LONG *CursorHidden ); -} + /*************************************************************************** + * IVideoWindow interface + */ + [ + object, + uuid(56a868b4-0ad4-11ce-b03a-0020af0ba770), + pointer_default(unique) + ] + interface IVideoWindow : IDispatch + { + [propput] HRESULT Caption( [in] BSTR strCaption ); + [propget] HRESULT Caption( [out] BSTR *strCaption ); + [propput] HRESULT WindowStyle( [in] LONG WindowStyle ); + [propget] HRESULT WindowStyle( [out] LONG *WindowStyle ); + [propput] HRESULT WindowStyleEx( [in] LONG WindowStyleEx ); + [propget] HRESULT WindowStyleEx( [out] LONG *WindowStyleEx ); + [propput] HRESULT AutoShow( [in] LONG AutoShow ); + [propget] HRESULT AutoShow( [out] LONG *AutoShow ); + [propput] HRESULT WindowState( [in] LONG WindowState ); + [propget] HRESULT WindowState( [out] LONG *WindowState ); + [propput] HRESULT BackgroundPalette( [in] LONG BackgroundPalette ); + [propget] HRESULT BackgroundPalette( [out] LONG *pBackgroundPalette ); + [propput] HRESULT Visible( [in] LONG Visible ); + [propget] HRESULT Visible( [out] LONG *pVisible ); + [propput] HRESULT Left( [in] LONG Left ); + [propget] HRESULT Left( [out] LONG *pLeft ); + [propput] HRESULT Width( [in] LONG Width ); + [propget] HRESULT Width( [out] LONG *pWidth ); + [propput] HRESULT Top( [in] LONG Top ); + [propget] HRESULT Top( [out] LONG *pTop ); + [propput] HRESULT Height( [in] LONG Height ); + [propget] HRESULT Height( [out] LONG *pHeight ); + [propput] HRESULT Owner( [in] OAHWND Owner ); + [propget] HRESULT Owner( [out] OAHWND *Owner ); + [propput] HRESULT MessageDrain( [in] OAHWND Drain ); + [propget] HRESULT MessageDrain( [out] OAHWND *Drain ); + [propget] HRESULT BorderColor( [out] LONG *Color ); + [propput] HRESULT BorderColor( [in] LONG Color ); + [propget] HRESULT FullScreenMode( [out] LONG *FullScreenMode ); + [propput] HRESULT FullScreenMode( [in] LONG FullScreenMode ); + HRESULT SetWindowForeground( [in] LONG Focus ); + HRESULT NotifyOwnerMessage( [in] OAHWND hwnd, [in] LONG uMsg, [in] LONG_PTR wParam, [in] LONG_PTR lParam ); + HRESULT SetWindowPosition( [in] LONG Left, [in] LONG Top, [in] LONG Width, [in] LONG Height ); + HRESULT GetWindowPosition( [out] LONG *pLeft, [out] LONG *pTop, [out] LONG *pWidth, [out] LONG *pHeight ); + HRESULT GetMinIdealImageSize( [out] LONG *pWidth, [out] LONG *pHeight ); + HRESULT GetMaxIdealImageSize( [out] LONG *pWidth, [out] LONG *pHeight ); + HRESULT GetRestorePosition( [out] LONG *pLeft, [out] LONG *pTop, [out] LONG *pWidth, [out] LONG *pHeight ); + HRESULT HideCursor( [in] LONG HideCursor ); + HRESULT IsCursorHidden( [out] LONG *CursorHidden ); + } -/***************************************************************************** - * IBasicVideo interface - */ -[ - object, - uuid(56a868b5-0ad4-11ce-b03a-0020af0ba770), - pointer_default(unique) -] -interface IBasicVideo : IDispatch -{ - [propget] HRESULT AvgTimePerFrame( [out] REFTIME *pAvgTimePerFrame ); - [propget] HRESULT BitRate( [out] LONG *pBitRate ); - [propget] HRESULT BitErrorRate( [out] LONG *pBitErrorRate ); - [propget] HRESULT VideoWidth( [out] LONG *pVideoWidth ); - [propget] HRESULT VideoHeight( [out] LONG *pVideoHeight ); - [propput] HRESULT SourceLeft( [in] LONG SourceLeft ); - [propget] HRESULT SourceLeft( [out] LONG *pSourceLeft ); - [propput] HRESULT SourceWidth( [in] LONG SourceWidth ); - [propget] HRESULT SourceWidth( [out] LONG *pSourceWidth ); - [propput] HRESULT SourceTop( [in] LONG SourceTop ); - [propget] HRESULT SourceTop( [out] LONG *pSourceTop ); - [propput] HRESULT SourceHeight( [in] LONG SourceHeight ); - [propget] HRESULT SourceHeight( [out] LONG *pSourceHeight ); - [propput] HRESULT DestinationLeft( [in] LONG DestinationLeft ); - [propget] HRESULT DestinationLeft( [out] LONG *pDestinationLeft ); - [propput] HRESULT DestinationWidth( [in] LONG DestinationWidth ); - [propget] HRESULT DestinationWidth( [out] LONG *pDestinationWidth ); - [propput] HRESULT DestinationTop( [in] LONG DestinationTop ); - [propget] HRESULT DestinationTop( [out] LONG *pDestinationTop ); - [propput] HRESULT DestinationHeight( [in] LONG DestinationHeight ); - [propget] HRESULT DestinationHeight( [out] LONG *pDestinationHeight ); - HRESULT SetSourcePosition( [in] LONG Left, [in] LONG Top, [in] LONG Width, [in] LONG Height ); - HRESULT GetSourcePosition( [out] LONG *pLeft, [out] LONG *pTop, [out] LONG *pWidth, [out] LONG *pHeight ); - HRESULT SetDefaultSourcePosition(); - HRESULT SetDestinationPosition( [in] LONG Left, [in] LONG Top, [in] LONG Width, [in] LONG Height ); - HRESULT GetDestinationPosition( [out] LONG *pLeft, [out] LONG *pTop, [out] LONG *pWidth, [out] LONG *pHeight ); - HRESULT SetDefaultDestinationPosition(); - HRESULT GetVideoSize( [out] LONG *pWidth, [out] LONG *pHeight ); - HRESULT GetVideoPaletteEntries( [in] LONG StartIndex, - [in] LONG Entries, - [out] LONG *pRetrieved, - [out, size_is(Entries), length_is(*pRetrieved)] LONG *pPalette ); - HRESULT GetCurrentImage( [in, out] LONG *pBufferSize, - [out, size_is(*pBufferSize), length_is(*pBufferSize)] LONG *pDIBImage ); - HRESULT IsUsingDefaultSource(); - HRESULT IsUsingDefaultDestination(); -} + /*************************************************************************** + * IBasicVideo interface + */ + [ + object, + uuid(56a868b5-0ad4-11ce-b03a-0020af0ba770), + pointer_default(unique) + ] + interface IBasicVideo : IDispatch + { + [propget] HRESULT AvgTimePerFrame( [out] REFTIME *pAvgTimePerFrame ); + [propget] HRESULT BitRate( [out] LONG *pBitRate ); + [propget] HRESULT BitErrorRate( [out] LONG *pBitErrorRate ); + [propget] HRESULT VideoWidth( [out] LONG *pVideoWidth ); + [propget] HRESULT VideoHeight( [out] LONG *pVideoHeight ); + [propput] HRESULT SourceLeft( [in] LONG SourceLeft ); + [propget] HRESULT SourceLeft( [out] LONG *pSourceLeft ); + [propput] HRESULT SourceWidth( [in] LONG SourceWidth ); + [propget] HRESULT SourceWidth( [out] LONG *pSourceWidth ); + [propput] HRESULT SourceTop( [in] LONG SourceTop ); + [propget] HRESULT SourceTop( [out] LONG *pSourceTop ); + [propput] HRESULT SourceHeight( [in] LONG SourceHeight ); + [propget] HRESULT SourceHeight( [out] LONG *pSourceHeight ); + [propput] HRESULT DestinationLeft( [in] LONG DestinationLeft ); + [propget] HRESULT DestinationLeft( [out] LONG *pDestinationLeft ); + [propput] HRESULT DestinationWidth( [in] LONG DestinationWidth ); + [propget] HRESULT DestinationWidth( [out] LONG *pDestinationWidth ); + [propput] HRESULT DestinationTop( [in] LONG DestinationTop ); + [propget] HRESULT DestinationTop( [out] LONG *pDestinationTop ); + [propput] HRESULT DestinationHeight( [in] LONG DestinationHeight ); + [propget] HRESULT DestinationHeight( [out] LONG *pDestinationHeight ); + HRESULT SetSourcePosition( [in] LONG Left, [in] LONG Top, [in] LONG Width, [in] LONG Height ); + HRESULT GetSourcePosition( [out] LONG *pLeft, [out] LONG *pTop, [out] LONG *pWidth, [out] LONG *pHeight ); + HRESULT SetDefaultSourcePosition(); + HRESULT SetDestinationPosition( [in] LONG Left, [in] LONG Top, [in] LONG Width, [in] LONG Height ); + HRESULT GetDestinationPosition( [out] LONG *pLeft, [out] LONG *pTop, [out] LONG *pWidth, [out] LONG *pHeight ); + HRESULT SetDefaultDestinationPosition(); + HRESULT GetVideoSize( [out] LONG *pWidth, [out] LONG *pHeight ); + HRESULT GetVideoPaletteEntries( [in] LONG StartIndex, + [in] LONG Entries, + [out] LONG *pRetrieved, + [out, size_is(Entries), length_is(*pRetrieved)] LONG *pPalette ); + HRESULT GetCurrentImage( [in, out] LONG *pBufferSize, + [out, size_is(*pBufferSize), length_is(*pBufferSize)] LONG *pDIBImage ); + HRESULT IsUsingDefaultSource(); + HRESULT IsUsingDefaultDestination(); + } -[ - uuid(329bb360-f6ea-11d1-9038-00a0c9697298), - helpstring("IBasicVideo2"), - odl -] + [ + uuid(329bb360-f6ea-11d1-9038-00a0c9697298), + helpstring("IBasicVideo2"), + odl + ] -interface IBasicVideo2 : IBasicVideo -{ - HRESULT GetPreferredAspectRatio([out] LONG *plAspectX, [out] LONG *plAspectY); -} + interface IBasicVideo2 : IBasicVideo + { + HRESULT GetPreferredAspectRatio([out] LONG *plAspectX, [out] LONG *plAspectY); + } -/***************************************************************************** - * IMediaEvent interface - */ -[ - object, - uuid(56a868b6-0ad4-11ce-b03a-0020af0ba770), - pointer_default(unique) -] -interface IMediaEvent : IDispatch -{ - HRESULT GetEventHandle( [out] OAEVENT *hEvent ); - HRESULT GetEvent( [out] LONG *lEventCode, [out] LONG_PTR *lParam1, [out] LONG_PTR *lParam2, [in] LONG msTimeout ); - HRESULT WaitForCompletion( [in] LONG msTimeout, [out] LONG *pEvCode ); - HRESULT CancelDefaultHandling( [in] LONG lEvCode ); - HRESULT RestoreDefaultHandling( [in] LONG lEvCode ); - HRESULT FreeEventParams( [in] LONG lEvCode, [in] LONG_PTR lParam1, [in] LONG_PTR lParam2 ); -} + /*************************************************************************** + * IMediaEvent interface + */ + [ + object, + uuid(56a868b6-0ad4-11ce-b03a-0020af0ba770), + pointer_default(unique) + ] + interface IMediaEvent : IDispatch + { + HRESULT GetEventHandle( [out] OAEVENT *hEvent ); + HRESULT GetEvent( [out] LONG *lEventCode, [out] LONG_PTR *lParam1, [out] LONG_PTR *lParam2, [in] LONG msTimeout ); + HRESULT WaitForCompletion( [in] LONG msTimeout, [out] LONG *pEvCode ); + HRESULT CancelDefaultHandling( [in] LONG lEvCode ); + HRESULT RestoreDefaultHandling( [in] LONG lEvCode ); + HRESULT FreeEventParams( [in] LONG lEvCode, [in] LONG_PTR lParam1, [in] LONG_PTR lParam2 ); + } -/***************************************************************************** - * IMediaEventEx interface - */ -[ - object, - uuid(56a868c0-0ad4-11ce-b03a-0020af0ba770), - pointer_default(unique) -] -interface IMediaEventEx : IMediaEvent -{ - HRESULT SetNotifyWindow( [in] OAHWND hwnd, [in] LONG lMsg, [in] LONG_PTR lInstanceData ); - HRESULT SetNotifyFlags( [in] LONG lNoNotifyFlags ); - HRESULT GetNotifyFlags( [out] LONG *lplNoNotifyFlags ); -} + /*************************************************************************** + * IMediaEventEx interface + */ + [ + object, + uuid(56a868c0-0ad4-11ce-b03a-0020af0ba770), + pointer_default(unique) + ] + interface IMediaEventEx : IMediaEvent + { + HRESULT SetNotifyWindow( [in] OAHWND hwnd, [in] LONG lMsg, [in] LONG_PTR lInstanceData ); + HRESULT SetNotifyFlags( [in] LONG lNoNotifyFlags ); + HRESULT GetNotifyFlags( [out] LONG *lplNoNotifyFlags ); + } -/***************************************************************************** - * IMediaPosition interface - */ -[ - object, - uuid(56a868b2-0ad4-11ce-b03a-0020af0ba770), - pointer_default(unique) -] -interface IMediaPosition : IDispatch -{ - HRESULT get_Duration( [out] REFTIME *plength ); - HRESULT put_CurrentPosition( [in] REFTIME llTime ); - HRESULT get_CurrentPosition( [out] REFTIME *pllTime ); - HRESULT get_StopTime( [out] REFTIME *pllTime ); - HRESULT put_StopTime( [in] REFTIME llTime ); - HRESULT get_PrerollTime( [out] REFTIME *pllTime ); - HRESULT put_PrerollTime( [in] REFTIME llTime ); - HRESULT put_Rate( [in] double dRate ); - HRESULT get_Rate( [out] double *pdRate ); - HRESULT CanSeekForward( [out] LONG *pCanSeekForward ); - HRESULT CanSeekBackward( [out] LONG *pCanSeekBackward ); -} + /*************************************************************************** + * IMediaPosition interface + */ + [ + object, + uuid(56a868b2-0ad4-11ce-b03a-0020af0ba770), + pointer_default(unique) + ] + interface IMediaPosition : IDispatch + { + HRESULT get_Duration( [out] REFTIME *plength ); + HRESULT put_CurrentPosition( [in] REFTIME llTime ); + HRESULT get_CurrentPosition( [out] REFTIME *pllTime ); + HRESULT get_StopTime( [out] REFTIME *pllTime ); + HRESULT put_StopTime( [in] REFTIME llTime ); + HRESULT get_PrerollTime( [out] REFTIME *pllTime ); + HRESULT put_PrerollTime( [in] REFTIME llTime ); + HRESULT put_Rate( [in] double dRate ); + HRESULT get_Rate( [out] double *pdRate ); + HRESULT CanSeekForward( [out] LONG *pCanSeekForward ); + HRESULT CanSeekBackward( [out] LONG *pCanSeekBackward ); + } + +} /* library QuartzTypeLib */ diff --git a/reactos/include/psdk/strmif.idl b/reactos/include/psdk/strmif.idl index a1cad6ba00e..a06f99b7517 100644 --- a/reactos/include/psdk/strmif.idl +++ b/reactos/include/psdk/strmif.idl @@ -16,6 +16,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +import "unknwn.idl"; import "objidl.idl"; #include diff --git a/reactos/include/psdk/winbase.h b/reactos/include/psdk/winbase.h index a123ebd76ae..d826ec16ae6 100644 --- a/reactos/include/psdk/winbase.h +++ b/reactos/include/psdk/winbase.h @@ -768,10 +768,15 @@ typedef struct _DEBUG_EVENT { typedef struct _OVERLAPPED { ULONG_PTR Internal; ULONG_PTR InternalHigh; - DWORD Offset; - DWORD OffsetHigh; + union { + struct { + DWORD Offset; + DWORD OffsetHigh; + } DUMMYSTRUCTNAME; + PVOID Pointer; + } DUMMYUNIONNAME; HANDLE hEvent; -} OVERLAPPED,*POVERLAPPED,*LPOVERLAPPED; +} OVERLAPPED, *POVERLAPPED, *LPOVERLAPPED; typedef struct _STARTUPINFOA { DWORD cb; diff --git a/reactos/include/reactos/wine/strmbase.h b/reactos/include/reactos/wine/strmbase.h new file mode 100644 index 00000000000..ecb53c41c6d --- /dev/null +++ b/reactos/include/reactos/wine/strmbase.h @@ -0,0 +1,660 @@ +/* + * Header file for Wine's strmbase implementation + * + * Copyright 2003 Robert Shearman + * Copyright 2010 Aric Stewart, CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +HRESULT WINAPI CopyMediaType(AM_MEDIA_TYPE * pDest, const AM_MEDIA_TYPE *pSrc); +void WINAPI FreeMediaType(AM_MEDIA_TYPE * pMediaType); +AM_MEDIA_TYPE * WINAPI CreateMediaType(AM_MEDIA_TYPE const * pSrc); +void WINAPI DeleteMediaType(AM_MEDIA_TYPE * pMediaType); + +/* Pin functions */ + +typedef struct BasePin +{ + IPin IPin_iface; + LONG refCount; + LPCRITICAL_SECTION pCritSec; + PIN_INFO pinInfo; + IPin * pConnectedTo; + AM_MEDIA_TYPE mtCurrent; + REFERENCE_TIME tStart; + REFERENCE_TIME tStop; + double dRate; + + const struct BasePinFuncTable* pFuncsTable; +} BasePin; + +typedef HRESULT (WINAPI *BasePin_CheckMediaType)(BasePin *This, const AM_MEDIA_TYPE *pmt); +typedef HRESULT (WINAPI *BasePin_AttemptConnection)(BasePin *This, IPin *pReceivePin, const AM_MEDIA_TYPE *pmt); +typedef LONG (WINAPI *BasePin_GetMediaTypeVersion)(BasePin *This); +typedef HRESULT (WINAPI *BasePin_GetMediaType)(BasePin *This, int iPosition, AM_MEDIA_TYPE *amt); + +typedef struct BasePinFuncTable { + /* Required for Input Pins*/ + BasePin_CheckMediaType pfnCheckMediaType; + /* Required for Output Pins*/ + BasePin_AttemptConnection pfnAttemptConnection; + /* Required for BasePinImpl_EnumMediaTypes */ + BasePin_GetMediaTypeVersion pfnGetMediaTypeVersion; + BasePin_GetMediaType pfnGetMediaType; +} BasePinFuncTable; + +typedef struct BaseOutputPin +{ + /* inheritance C style! */ + BasePin pin; + IMemInputPin * pMemInputPin; + IMemAllocator * pAllocator; + + const struct BaseOutputPinFuncTable* pFuncsTable; +} BaseOutputPin; + +typedef HRESULT (WINAPI *BaseOutputPin_DecideBufferSize)(BaseOutputPin *This, IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest); +typedef HRESULT (WINAPI *BaseOutputPin_DecideAllocator)(BaseOutputPin *This, IMemInputPin *pPin, IMemAllocator **pAlloc); +typedef HRESULT (WINAPI *BaseOutputPin_BreakConnect)(BaseOutputPin * This); + +typedef struct BaseOutputPinFuncTable { + /* Required for BaseOutputPinImpl_DecideAllocator */ + BaseOutputPin_DecideBufferSize pfnDecideBufferSize; + /* Required for BaseOutputPinImpl_AttemptConnection */ + BaseOutputPin_DecideAllocator pfnDecideAllocator; + BaseOutputPin_BreakConnect pfnBreakConnect; +} BaseOutputPinFuncTable; + +typedef struct BaseInputPin +{ + /* inheritance C style! */ + BasePin pin; + + IMemInputPin IMemInputPin_iface; + IMemAllocator * pAllocator; + BOOL flushing, end_of_stream; + IMemAllocator *preferred_allocator; + + const struct BaseInputPinFuncTable* pFuncsTable; +} BaseInputPin; + +typedef HRESULT (WINAPI *BaseInputPin_Receive)(BaseInputPin *This, IMediaSample *pSample); + +typedef struct BaseInputPinFuncTable { + /* Optional */ + BaseInputPin_Receive pfnReceive; +} BaseInputPinFuncTable; + +/* Base Pin */ +HRESULT WINAPI BasePinImpl_GetMediaType(BasePin *This, int iPosition, AM_MEDIA_TYPE *pmt); +LONG WINAPI BasePinImpl_GetMediaTypeVersion(BasePin *This); +ULONG WINAPI BasePinImpl_AddRef(IPin * iface); +HRESULT WINAPI BasePinImpl_Disconnect(IPin * iface); +HRESULT WINAPI BasePinImpl_ConnectedTo(IPin * iface, IPin ** ppPin); +HRESULT WINAPI BasePinImpl_ConnectionMediaType(IPin * iface, AM_MEDIA_TYPE * pmt); +HRESULT WINAPI BasePinImpl_QueryPinInfo(IPin * iface, PIN_INFO * pInfo); +HRESULT WINAPI BasePinImpl_QueryDirection(IPin * iface, PIN_DIRECTION * pPinDir); +HRESULT WINAPI BasePinImpl_QueryId(IPin * iface, LPWSTR * Id); +HRESULT WINAPI BasePinImpl_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt); +HRESULT WINAPI BasePinImpl_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum); +HRESULT WINAPI BasePinImpl_QueryInternalConnections(IPin * iface, IPin ** apPin, ULONG * cPin); +HRESULT WINAPI BasePinImpl_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate); + +/* Base Output Pin */ +HRESULT WINAPI BaseOutputPinImpl_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv); +ULONG WINAPI BaseOutputPinImpl_Release(IPin * iface); +HRESULT WINAPI BaseOutputPinImpl_Connect(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt); +HRESULT WINAPI BaseOutputPinImpl_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt); +HRESULT WINAPI BaseOutputPinImpl_Disconnect(IPin * iface); +HRESULT WINAPI BaseOutputPinImpl_EndOfStream(IPin * iface); +HRESULT WINAPI BaseOutputPinImpl_BeginFlush(IPin * iface); +HRESULT WINAPI BaseOutputPinImpl_EndFlush(IPin * iface); + +HRESULT WINAPI BaseOutputPinImpl_GetDeliveryBuffer(BaseOutputPin * This, IMediaSample ** ppSample, REFERENCE_TIME * tStart, REFERENCE_TIME * tStop, DWORD dwFlags); +HRESULT WINAPI BaseOutputPinImpl_Deliver(BaseOutputPin * This, IMediaSample * pSample); +HRESULT WINAPI BaseOutputPinImpl_BreakConnect(BaseOutputPin * This); +HRESULT WINAPI BaseOutputPinImpl_Active(BaseOutputPin * This); +HRESULT WINAPI BaseOutputPinImpl_Inactive(BaseOutputPin * This); +HRESULT WINAPI BaseOutputPinImpl_InitAllocator(BaseOutputPin *This, IMemAllocator **pMemAlloc); +HRESULT WINAPI BaseOutputPinImpl_DecideAllocator(BaseOutputPin *This, IMemInputPin *pPin, IMemAllocator **pAlloc); +HRESULT WINAPI BaseOutputPinImpl_AttemptConnection(BasePin *This, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt); + +HRESULT WINAPI BaseOutputPin_Construct(const IPinVtbl *OutputPin_Vtbl, LONG outputpin_size, const PIN_INFO * pPinInfo, const BasePinFuncTable* pBaseFuncsTable, const BaseOutputPinFuncTable* pBaseOutputFuncsTable, LPCRITICAL_SECTION pCritSec, IPin ** ppPin); + +/* Base Input Pin */ +HRESULT WINAPI BaseInputPinImpl_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv); +ULONG WINAPI BaseInputPinImpl_Release(IPin * iface); +HRESULT WINAPI BaseInputPinImpl_Connect(IPin * iface, IPin * pConnector, const AM_MEDIA_TYPE * pmt); +HRESULT WINAPI BaseInputPinImpl_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt); +HRESULT WINAPI BaseInputPinImpl_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt); +HRESULT WINAPI BaseInputPinImpl_EndOfStream(IPin * iface); +HRESULT WINAPI BaseInputPinImpl_BeginFlush(IPin * iface); +HRESULT WINAPI BaseInputPinImpl_EndFlush(IPin * iface); +HRESULT WINAPI BaseInputPinImpl_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate); + +HRESULT BaseInputPin_Construct(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo, const BasePinFuncTable* pBaseFuncsTable, const BaseInputPinFuncTable* pBaseInputFuncsTable, LPCRITICAL_SECTION pCritSec, IMemAllocator *, IPin ** ppPin); + +typedef struct BaseFilter +{ + IBaseFilter IBaseFilter_iface; + LONG refCount; + CRITICAL_SECTION csFilter; + + FILTER_STATE state; + REFERENCE_TIME rtStreamStart; + IReferenceClock * pClock; + FILTER_INFO filterInfo; + CLSID clsid; + LONG pinVersion; + + const struct BaseFilterFuncTable* pFuncsTable; +} BaseFilter; + +typedef IPin* (WINAPI *BaseFilter_GetPin)(BaseFilter* iface, int iPosition); +typedef LONG (WINAPI *BaseFilter_GetPinCount)(BaseFilter* iface); +typedef LONG (WINAPI *BaseFilter_GetPinVersion)(BaseFilter* iface); + +typedef struct BaseFilterFuncTable { + /* Required */ + BaseFilter_GetPin pfnGetPin; + BaseFilter_GetPinCount pfnGetPinCount; +} BaseFilterFuncTable; + +HRESULT WINAPI BaseFilterImpl_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv); +ULONG WINAPI BaseFilterImpl_AddRef(IBaseFilter * iface); +ULONG WINAPI BaseFilterImpl_Release(IBaseFilter * iface); +HRESULT WINAPI BaseFilterImpl_GetClassID(IBaseFilter * iface, CLSID * pClsid); +HRESULT WINAPI BaseFilterImpl_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState ); +HRESULT WINAPI BaseFilterImpl_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock); +HRESULT WINAPI BaseFilterImpl_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock); +HRESULT WINAPI BaseFilterImpl_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum); +HRESULT WINAPI BaseFilterImpl_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo); +HRESULT WINAPI BaseFilterImpl_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName ); +HRESULT WINAPI BaseFilterImpl_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo); + +LONG WINAPI BaseFilterImpl_GetPinVersion(BaseFilter* This); +VOID WINAPI BaseFilterImpl_IncrementPinVersion(BaseFilter* This); + +HRESULT WINAPI BaseFilter_Init(BaseFilter * This, const IBaseFilterVtbl *Vtbl, const CLSID *pClsid, DWORD_PTR DebugInfo, const BaseFilterFuncTable* pBaseFuncsTable); + +/* Enums */ +HRESULT WINAPI EnumMediaTypes_Construct(BasePin *iface, BasePin_GetMediaType enumFunc, BasePin_GetMediaTypeVersion versionFunc, IEnumMediaTypes ** ppEnum); + +HRESULT WINAPI EnumPins_Construct(BaseFilter *base, BaseFilter_GetPin receive_pin, BaseFilter_GetPinCount receive_pincount, BaseFilter_GetPinVersion receive_version, IEnumPins ** ppEnum); + +/* Transform Filter */ +typedef struct TransformFilter +{ + BaseFilter filter; + + IPin **ppPins; + ULONG npins; + AM_MEDIA_TYPE pmt; + CRITICAL_SECTION csReceive; + + const struct TransformFilterFuncTable * pFuncsTable; + struct QualityControlImpl *qcimpl; + /* IMediaSeeking and IMediaPosition are implemented by ISeekingPassThru */ + IUnknown *seekthru_unk; +} TransformFilter; + +typedef HRESULT (WINAPI *TransformFilter_DecideBufferSize) (TransformFilter *iface, IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest); +typedef HRESULT (WINAPI *TransformFilter_StartStreaming) (TransformFilter *iface); +typedef HRESULT (WINAPI *TransformFilter_StopStreaming) (TransformFilter *iface); +typedef HRESULT (WINAPI *TransformFilter_Receive) (TransformFilter* iface, IMediaSample* pIn); +typedef HRESULT (WINAPI *TransformFilter_CompleteConnect) (TransformFilter *iface, PIN_DIRECTION dir, IPin *pPin); +typedef HRESULT (WINAPI *TransformFilter_BreakConnect) (TransformFilter *iface, PIN_DIRECTION dir); +typedef HRESULT (WINAPI *TransformFilter_SetMediaType) (TransformFilter *iface, PIN_DIRECTION dir, const AM_MEDIA_TYPE *pMediaType); +typedef HRESULT (WINAPI *TransformFilter_CheckInputType) (TransformFilter *iface, const AM_MEDIA_TYPE *pMediaType); +typedef HRESULT (WINAPI *TransformFilter_EndOfStream) (TransformFilter *iface); +typedef HRESULT (WINAPI *TransformFilter_BeginFlush) (TransformFilter *iface); +typedef HRESULT (WINAPI *TransformFilter_EndFlush) (TransformFilter *iface); +typedef HRESULT (WINAPI *TransformFilter_NewSegment) (TransformFilter *iface, +REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate); +typedef HRESULT (WINAPI *TransformFilter_Notify) (TransformFilter *iface, IBaseFilter *sender, Quality qm); + +typedef struct TransformFilterFuncTable { + /* Required */ + TransformFilter_DecideBufferSize pfnDecideBufferSize; + /* Optional */ + TransformFilter_StartStreaming pfnStartStreaming; + TransformFilter_Receive pfnReceive; + TransformFilter_StopStreaming pfnStopStreaming; + TransformFilter_CheckInputType pfnCheckInputType; + TransformFilter_SetMediaType pfnSetMediaType; + TransformFilter_CompleteConnect pfnCompleteConnect; + TransformFilter_BreakConnect pfnBreakConnect; + TransformFilter_EndOfStream pfnEndOfStream; + TransformFilter_BeginFlush pfnBeginFlush; + TransformFilter_EndFlush pfnEndFlush; + TransformFilter_NewSegment pfnNewSegment; + TransformFilter_Notify pfnNotify; +} TransformFilterFuncTable; + +HRESULT WINAPI TransformFilterImpl_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv); +ULONG WINAPI TransformFilterImpl_Release(IBaseFilter * iface); +HRESULT WINAPI TransformFilterImpl_Stop(IBaseFilter * iface); +HRESULT WINAPI TransformFilterImpl_Pause(IBaseFilter * iface); +HRESULT WINAPI TransformFilterImpl_Run(IBaseFilter * iface, REFERENCE_TIME tStart); +HRESULT WINAPI TransformFilterImpl_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin); +HRESULT WINAPI TransformFilterImpl_Notify(TransformFilter *iface, IBaseFilter *sender, Quality qm); + +HRESULT TransformFilter_Construct( const IBaseFilterVtbl *filterVtbl, LONG filter_size, const CLSID* pClsid, const TransformFilterFuncTable* pFuncsTable, IBaseFilter ** ppTransformFilter); + +/* Source Seeking */ +typedef HRESULT (WINAPI *SourceSeeking_ChangeRate)(IMediaSeeking *iface); +typedef HRESULT (WINAPI *SourceSeeking_ChangeStart)(IMediaSeeking *iface); +typedef HRESULT (WINAPI *SourceSeeking_ChangeStop)(IMediaSeeking *iface); + +typedef struct SourceSeeking +{ + IMediaSeeking IMediaSeeking_iface; + + ULONG refCount; + SourceSeeking_ChangeStop fnChangeStop; + SourceSeeking_ChangeStart fnChangeStart; + SourceSeeking_ChangeRate fnChangeRate; + DWORD dwCapabilities; + double dRate; + LONGLONG llCurrent, llStop, llDuration; + GUID timeformat; + PCRITICAL_SECTION crst; +} SourceSeeking; + +HRESULT SourceSeeking_Init(SourceSeeking *pSeeking, const IMediaSeekingVtbl *Vtbl, SourceSeeking_ChangeStop fnChangeStop, SourceSeeking_ChangeStart fnChangeStart, SourceSeeking_ChangeRate fnChangeRate, PCRITICAL_SECTION crit_sect); + +HRESULT WINAPI SourceSeekingImpl_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities); +HRESULT WINAPI SourceSeekingImpl_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities); +HRESULT WINAPI SourceSeekingImpl_IsFormatSupported(IMediaSeeking * iface, const GUID * pFormat); +HRESULT WINAPI SourceSeekingImpl_QueryPreferredFormat(IMediaSeeking * iface, GUID * pFormat); +HRESULT WINAPI SourceSeekingImpl_GetTimeFormat(IMediaSeeking * iface, GUID * pFormat); +HRESULT WINAPI SourceSeekingImpl_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat); +HRESULT WINAPI SourceSeekingImpl_SetTimeFormat(IMediaSeeking * iface, const GUID * pFormat); +HRESULT WINAPI SourceSeekingImpl_GetDuration(IMediaSeeking * iface, LONGLONG * pDuration); +HRESULT WINAPI SourceSeekingImpl_GetStopPosition(IMediaSeeking * iface, LONGLONG * pStop); +HRESULT WINAPI SourceSeekingImpl_GetCurrentPosition(IMediaSeeking * iface, LONGLONG * pCurrent); +HRESULT WINAPI SourceSeekingImpl_ConvertTimeFormat(IMediaSeeking * iface, LONGLONG * pTarget, const GUID * pTargetFormat, LONGLONG Source, const GUID * pSourceFormat); +HRESULT WINAPI SourceSeekingImpl_SetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, DWORD dwCurrentFlags, LONGLONG * pStop, DWORD dwStopFlags); +HRESULT WINAPI SourceSeekingImpl_GetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, LONGLONG * pStop); +HRESULT WINAPI SourceSeekingImpl_GetAvailable(IMediaSeeking * iface, LONGLONG * pEarliest, LONGLONG * pLatest); +HRESULT WINAPI SourceSeekingImpl_SetRate(IMediaSeeking * iface, double dRate); +HRESULT WINAPI SourceSeekingImpl_GetRate(IMediaSeeking * iface, double * dRate); +HRESULT WINAPI SourceSeekingImpl_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll); + +/* PosPassThru */ +HRESULT WINAPI RendererPosPassThru_RegisterMediaTime(IUnknown *iface, REFERENCE_TIME start); +HRESULT WINAPI RendererPosPassThru_ResetMediaTime(IUnknown *iface); +HRESULT WINAPI RendererPosPassThru_EOS(IUnknown *iface); + +HRESULT WINAPI CreatePosPassThru(IUnknown* pUnkOuter, BOOL bRenderer, IPin *pPin, IUnknown **ppPassThru); +HRESULT WINAPI PosPassThru_Construct(IUnknown* pUnkOuter, LPVOID *ppPassThru); + +/* Filter Registration */ + +typedef REGPINTYPES AMOVIESETUP_MEDIATYPE; +typedef REGFILTERPINS AMOVIESETUP_PIN; + +typedef struct AMOVIESETUP_FILTER { + const CLSID *clsid; + const WCHAR *name; + DWORD merit; + UINT pins; + const AMOVIESETUP_PIN *pPin; +} AMOVIESETUP_FILTER, *LPAMOVIESETUP_FILTER; + +typedef IUnknown *(CALLBACK *LPFNNewCOMObject)(LPUNKNOWN pUnkOuter, HRESULT *phr); +typedef void (CALLBACK *LPFNInitRoutine)(BOOL bLoading, const CLSID *rclsid); + +typedef struct tagFactoryTemplate { + const WCHAR *m_Name; + const CLSID *m_ClsID; + LPFNNewCOMObject m_lpfnNew; + LPFNInitRoutine m_lpfnInit; + const AMOVIESETUP_FILTER *m_pAMovieSetup_Filter; +} FactoryTemplate; + +HRESULT WINAPI AMovieDllRegisterServer2(BOOL bRegister); +HRESULT WINAPI AMovieSetupRegisterFilter2(const AMOVIESETUP_FILTER *pFilter, IFilterMapper2 *pIFM2, BOOL bRegister); + +/* Output Queue */ +typedef struct tagOutputQueue { + CRITICAL_SECTION csQueue; + + BaseOutputPin * pInputPin; + + HANDLE hThread; + HANDLE hProcessQueue; + + LONG lBatchSize; + BOOL bBatchExact; + BOOL bTerminate; + BOOL bSendAnyway; + + struct list *SampleList; + + const struct OutputQueueFuncTable* pFuncsTable; +} OutputQueue; + +typedef DWORD (WINAPI *OutputQueue_ThreadProc)(OutputQueue *This); + +typedef struct OutputQueueFuncTable +{ + OutputQueue_ThreadProc pfnThreadProc; +} OutputQueueFuncTable; + +HRESULT WINAPI OutputQueue_Construct( BaseOutputPin *pInputPin, BOOL bAuto, + BOOL bQueue, LONG lBatchSize, BOOL bBatchExact, DWORD dwPriority, + const OutputQueueFuncTable* pFuncsTable, OutputQueue **ppOutputQueue ); +HRESULT WINAPI OutputQueue_Destroy(OutputQueue *pOutputQueue); +HRESULT WINAPI OutputQueue_ReceiveMultiple(OutputQueue *pOutputQueue, IMediaSample **ppSamples, LONG nSamples, LONG *nSamplesProcessed); +HRESULT WINAPI OutputQueue_Receive(OutputQueue *pOutputQueue, IMediaSample *pSample); +VOID WINAPI OutputQueue_EOS(OutputQueue *pOutputQueue); +VOID WINAPI OutputQueue_SendAnyway(OutputQueue *pOutputQueue); +DWORD WINAPI OutputQueueImpl_ThreadProc(OutputQueue *pOutputQueue); + +typedef struct tagBaseWindow +{ + HWND hWnd; + LONG Width; + LONG Height; + HINSTANCE hInstance; + LPWSTR pClassName; + DWORD ClassStyles; + DWORD WindowStyles; + DWORD WindowStylesEx; + HDC hDC; + + const struct BaseWindowFuncTable* pFuncsTable; +} BaseWindow; + +typedef LPWSTR (WINAPI *BaseWindow_GetClassWindowStyles)(BaseWindow *This, DWORD *pClassStyles, DWORD *pWindowStyles, DWORD *pWindowStylesEx); +typedef RECT (WINAPI *BaseWindow_GetDefaultRect)(BaseWindow *This); +typedef BOOL (WINAPI *BaseWindow_PossiblyEatMessage)(BaseWindow *This, UINT uMsg, WPARAM wParam, LPARAM lParam); +typedef LRESULT (WINAPI *BaseWindow_OnReceiveMessage)(BaseWindow *This, HWND hwnd, INT uMsg, WPARAM wParam, LPARAM lParam); +typedef BOOL (WINAPI *BaseWindow_OnSize)(BaseWindow *This, LONG Height, LONG Width); + +typedef struct BaseWindowFuncTable +{ + /* Required */ + BaseWindow_GetClassWindowStyles pfnGetClassWindowStyles; + BaseWindow_GetDefaultRect pfnGetDefaultRect; + /* Optional, WinProc Related */ + BaseWindow_OnReceiveMessage pfnOnReceiveMessage; + BaseWindow_PossiblyEatMessage pfnPossiblyEatMessage; + BaseWindow_OnSize pfnOnSize; +} BaseWindowFuncTable; + +HRESULT WINAPI BaseWindow_Init(BaseWindow *pBaseWindow, const BaseWindowFuncTable* pFuncsTable); +HRESULT WINAPI BaseWindow_Destroy(BaseWindow *pBaseWindow); + +HRESULT WINAPI BaseWindowImpl_PrepareWindow(BaseWindow *This); +HRESULT WINAPI BaseWindowImpl_DoneWithWindow(BaseWindow *This); +RECT WINAPI BaseWindowImpl_GetDefaultRect(BaseWindow *This); +LRESULT WINAPI BaseWindowImpl_OnReceiveMessage(BaseWindow *This, HWND hwnd, INT uMsg, WPARAM wParam, LPARAM lParam); +BOOL WINAPI BaseWindowImpl_OnSize(BaseWindow *This, LONG Height, LONG Width); + +typedef struct{ + ITypeInfo *pTypeInfo; +} BaseDispatch; + +HRESULT WINAPI BaseDispatch_Init(BaseDispatch *This, REFIID riid); +HRESULT WINAPI BaseDispatch_Destroy(BaseDispatch *This); +HRESULT WINAPI BaseDispatchImpl_GetIDsOfNames(BaseDispatch *This, REFIID riid, OLECHAR **rgszNames, UINT cNames, LCID lcid, DISPID *rgdispid); +HRESULT WINAPI BaseDispatchImpl_GetTypeInfo(BaseDispatch *This, REFIID riid, UINT itinfo, LCID lcid, ITypeInfo **pptinfo); +HRESULT WINAPI BaseDispatchImpl_GetTypeInfoCount(BaseDispatch *This, UINT *pctinfo); + +#ifdef __IVideoWindow_FWD_DEFINED__ +typedef struct tagBaseControlWindow +{ + BaseWindow baseWindow; + IVideoWindow IVideoWindow_iface; + BaseDispatch baseDispatch; + + BOOL AutoShow; + HWND hwndDrain; + HWND hwndOwner; + BaseFilter* pFilter; + CRITICAL_SECTION* pInterfaceLock; + BasePin* pPin; +} BaseControlWindow; + +HRESULT WINAPI BaseControlWindow_Init(BaseControlWindow *pControlWindow, const IVideoWindowVtbl *lpVtbl, BaseFilter *owner, CRITICAL_SECTION *lock, BasePin* pPin, const BaseWindowFuncTable* pFuncsTable); +HRESULT WINAPI BaseControlWindow_Destroy(BaseControlWindow *pControlWindow); + +BOOL WINAPI BaseControlWindowImpl_PossiblyEatMessage(BaseWindow *This, UINT uMsg, WPARAM wParam, LPARAM lParam); +HRESULT WINAPI BaseControlWindowImpl_GetTypeInfoCount(IVideoWindow *iface, UINT*pctinfo); +HRESULT WINAPI BaseControlWindowImpl_GetTypeInfo(IVideoWindow *iface, UINT iTInfo, LCID lcid, ITypeInfo**ppTInfo); +HRESULT WINAPI BaseControlWindowImpl_GetIDsOfNames(IVideoWindow *iface, REFIID riid, LPOLESTR*rgszNames, UINT cNames, LCID lcid, DISPID*rgDispId); +HRESULT WINAPI BaseControlWindowImpl_Invoke(IVideoWindow *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS*pDispParams, VARIANT*pVarResult, EXCEPINFO*pExepInfo, UINT*puArgErr); +HRESULT WINAPI BaseControlWindowImpl_put_Caption(IVideoWindow *iface, BSTR strCaption); +HRESULT WINAPI BaseControlWindowImpl_get_Caption(IVideoWindow *iface, BSTR *strCaption); +HRESULT WINAPI BaseControlWindowImpl_put_WindowStyle(IVideoWindow *iface, LONG WindowStyle); +HRESULT WINAPI BaseControlWindowImpl_get_WindowStyle(IVideoWindow *iface, LONG *WindowStyle); +HRESULT WINAPI BaseControlWindowImpl_put_WindowStyleEx(IVideoWindow *iface, LONG WindowStyleEx); +HRESULT WINAPI BaseControlWindowImpl_get_WindowStyleEx(IVideoWindow *iface, LONG *WindowStyleEx); +HRESULT WINAPI BaseControlWindowImpl_put_AutoShow(IVideoWindow *iface, LONG AutoShow); +HRESULT WINAPI BaseControlWindowImpl_get_AutoShow(IVideoWindow *iface, LONG *AutoShow); +HRESULT WINAPI BaseControlWindowImpl_put_WindowState(IVideoWindow *iface, LONG WindowState); +HRESULT WINAPI BaseControlWindowImpl_get_WindowState(IVideoWindow *iface, LONG *WindowState); +HRESULT WINAPI BaseControlWindowImpl_put_BackgroundPalette(IVideoWindow *iface, LONG BackgroundPalette); +HRESULT WINAPI BaseControlWindowImpl_get_BackgroundPalette(IVideoWindow *iface, LONG *pBackgroundPalette); +HRESULT WINAPI BaseControlWindowImpl_put_Visible(IVideoWindow *iface, LONG Visible); +HRESULT WINAPI BaseControlWindowImpl_get_Visible(IVideoWindow *iface, LONG *pVisible); +HRESULT WINAPI BaseControlWindowImpl_put_Left(IVideoWindow *iface, LONG Left); +HRESULT WINAPI BaseControlWindowImpl_get_Left(IVideoWindow *iface, LONG *pLeft); +HRESULT WINAPI BaseControlWindowImpl_put_Width(IVideoWindow *iface, LONG Width); +HRESULT WINAPI BaseControlWindowImpl_get_Width(IVideoWindow *iface, LONG *pWidth); +HRESULT WINAPI BaseControlWindowImpl_put_Top(IVideoWindow *iface, LONG Top); +HRESULT WINAPI BaseControlWindowImpl_get_Top(IVideoWindow *iface, LONG *pTop); + +HRESULT WINAPI BaseControlWindowImpl_put_Height(IVideoWindow *iface, LONG Height); +HRESULT WINAPI BaseControlWindowImpl_get_Height(IVideoWindow *iface, LONG *pHeight); +HRESULT WINAPI BaseControlWindowImpl_put_Owner(IVideoWindow *iface, OAHWND Owner); +HRESULT WINAPI BaseControlWindowImpl_get_Owner(IVideoWindow *iface, OAHWND *Owner); +HRESULT WINAPI BaseControlWindowImpl_put_MessageDrain(IVideoWindow *iface, OAHWND Drain); +HRESULT WINAPI BaseControlWindowImpl_get_MessageDrain(IVideoWindow *iface, OAHWND *Drain); +HRESULT WINAPI BaseControlWindowImpl_get_BorderColor(IVideoWindow *iface, LONG *Color); +HRESULT WINAPI BaseControlWindowImpl_put_BorderColor(IVideoWindow *iface, LONG Color); +HRESULT WINAPI BaseControlWindowImpl_get_FullScreenMode(IVideoWindow *iface, LONG *FullScreenMode); +HRESULT WINAPI BaseControlWindowImpl_put_FullScreenMode(IVideoWindow *iface, LONG FullScreenMode); +HRESULT WINAPI BaseControlWindowImpl_SetWindowForeground(IVideoWindow *iface, LONG Focus); +HRESULT WINAPI BaseControlWindowImpl_SetWindowPosition(IVideoWindow *iface, LONG Left, LONG Top, LONG Width, LONG Height); +HRESULT WINAPI BaseControlWindowImpl_GetWindowPosition(IVideoWindow *iface, LONG *pLeft, LONG *pTop, LONG *pWidth, LONG *pHeight); +HRESULT WINAPI BaseControlWindowImpl_NotifyOwnerMessage(IVideoWindow *iface, OAHWND hwnd, LONG uMsg, LONG_PTR wParam, LONG_PTR lParam); +HRESULT WINAPI BaseControlWindowImpl_GetMinIdealImageSize(IVideoWindow *iface, LONG *pWidth, LONG *pHeight); +HRESULT WINAPI BaseControlWindowImpl_GetMaxIdealImageSize(IVideoWindow *iface, LONG *pWidth, LONG *pHeight); +HRESULT WINAPI BaseControlWindowImpl_GetRestorePosition(IVideoWindow *iface, LONG *pLeft, LONG *pTop, LONG *pWidth, LONG *pHeight); +HRESULT WINAPI BaseControlWindowImpl_HideCursor(IVideoWindow *iface, LONG HideCursor); +HRESULT WINAPI BaseControlWindowImpl_IsCursorHidden(IVideoWindow *iface, LONG *CursorHidden); +#endif + +#ifdef __IBasicVideo_FWD_DEFINED__ +#ifdef __amvideo_h__ +typedef struct tagBaseControlVideo +{ + IBasicVideo IBasicVideo_iface; + BaseDispatch baseDispatch; + + BaseFilter* pFilter; + CRITICAL_SECTION* pInterfaceLock; + BasePin* pPin; + + const struct BaseControlVideoFuncTable* pFuncsTable; +} BaseControlVideo; + +typedef HRESULT (WINAPI *BaseControlVideo_GetSourceRect)(BaseControlVideo* This, RECT *pSourceRect); +typedef HRESULT (WINAPI *BaseControlVideo_GetStaticImage)(BaseControlVideo* This, LONG *pBufferSize, LONG *pDIBImage); +typedef HRESULT (WINAPI *BaseControlVideo_GetTargetRect)(BaseControlVideo* This, RECT *pTargetRect); +typedef VIDEOINFOHEADER* (WINAPI *BaseControlVideo_GetVideoFormat)(BaseControlVideo* This); +typedef HRESULT (WINAPI *BaseControlVideo_IsDefaultSourceRect)(BaseControlVideo* This); +typedef HRESULT (WINAPI *BaseControlVideo_IsDefaultTargetRect)(BaseControlVideo* This); +typedef HRESULT (WINAPI *BaseControlVideo_SetDefaultSourceRect)(BaseControlVideo* This); +typedef HRESULT (WINAPI *BaseControlVideo_SetDefaultTargetRect)(BaseControlVideo* This); +typedef HRESULT (WINAPI *BaseControlVideo_SetSourceRect)(BaseControlVideo* This, RECT *pSourceRect); +typedef HRESULT (WINAPI *BaseControlVideo_SetTargetRect)(BaseControlVideo* This, RECT *pTargetRect); + +typedef struct BaseControlVideoFuncTable { + /* Required */ + BaseControlVideo_GetSourceRect pfnGetSourceRect; + BaseControlVideo_GetStaticImage pfnGetStaticImage; + BaseControlVideo_GetTargetRect pfnGetTargetRect; + BaseControlVideo_GetVideoFormat pfnGetVideoFormat; + BaseControlVideo_IsDefaultSourceRect pfnIsDefaultSourceRect; + BaseControlVideo_IsDefaultTargetRect pfnIsDefaultTargetRect; + BaseControlVideo_SetDefaultSourceRect pfnSetDefaultSourceRect; + BaseControlVideo_SetDefaultTargetRect pfnSetDefaultTargetRect; + BaseControlVideo_SetSourceRect pfnSetSourceRect; + BaseControlVideo_SetTargetRect pfnSetTargetRect; +} BaseControlVideoFuncTable; + +HRESULT WINAPI BaseControlVideo_Init(BaseControlVideo *pControlVideo, const IBasicVideoVtbl *lpVtbl, BaseFilter *owner, CRITICAL_SECTION *lock, BasePin* pPin, const BaseControlVideoFuncTable* pFuncsTable); +HRESULT WINAPI BaseControlVideo_Destroy(BaseControlVideo *pControlVideo); + +HRESULT WINAPI BaseControlVideoImpl_GetTypeInfoCount(IBasicVideo *iface, UINT*pctinfo); +HRESULT WINAPI BaseControlVideoImpl_GetTypeInfo(IBasicVideo *iface, UINT iTInfo, LCID lcid, ITypeInfo**ppTInfo); +HRESULT WINAPI BaseControlVideoImpl_GetIDsOfNames(IBasicVideo *iface, REFIID riid, LPOLESTR*rgszNames, UINT cNames, LCID lcid, DISPID*rgDispId); +HRESULT WINAPI BaseControlVideoImpl_Invoke(IBasicVideo *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS*pDispParams, VARIANT*pVarResult, EXCEPINFO*pExepInfo, UINT*puArgErr); +HRESULT WINAPI BaseControlVideoImpl_get_AvgTimePerFrame(IBasicVideo *iface, REFTIME *pAvgTimePerFrame); +HRESULT WINAPI BaseControlVideoImpl_get_BitRate(IBasicVideo *iface, LONG *pBitRate); +HRESULT WINAPI BaseControlVideoImpl_get_BitErrorRate(IBasicVideo *iface, LONG *pBitErrorRate); +HRESULT WINAPI BaseControlVideoImpl_get_VideoWidth(IBasicVideo *iface, LONG *pVideoWidth); +HRESULT WINAPI BaseControlVideoImpl_get_VideoHeight(IBasicVideo *iface, LONG *pVideoHeight); +HRESULT WINAPI BaseControlVideoImpl_put_SourceLeft(IBasicVideo *iface, LONG SourceLeft); +HRESULT WINAPI BaseControlVideoImpl_get_SourceLeft(IBasicVideo *iface, LONG *pSourceLeft); +HRESULT WINAPI BaseControlVideoImpl_put_SourceWidth(IBasicVideo *iface, LONG SourceWidth); +HRESULT WINAPI BaseControlVideoImpl_get_SourceWidth(IBasicVideo *iface, LONG *pSourceWidth); +HRESULT WINAPI BaseControlVideoImpl_put_SourceTop(IBasicVideo *iface, LONG SourceTop); +HRESULT WINAPI BaseControlVideoImpl_get_SourceTop(IBasicVideo *iface, LONG *pSourceTop); +HRESULT WINAPI BaseControlVideoImpl_put_SourceHeight(IBasicVideo *iface, LONG SourceHeight); +HRESULT WINAPI BaseControlVideoImpl_get_SourceHeight(IBasicVideo *iface, LONG *pSourceHeight); +HRESULT WINAPI BaseControlVideoImpl_put_DestinationLeft(IBasicVideo *iface, LONG DestinationLeft); +HRESULT WINAPI BaseControlVideoImpl_get_DestinationLeft(IBasicVideo *iface, LONG *pDestinationLeft); +HRESULT WINAPI BaseControlVideoImpl_put_DestinationWidth(IBasicVideo *iface, LONG DestinationWidth); +HRESULT WINAPI BaseControlVideoImpl_get_DestinationWidth(IBasicVideo *iface, LONG *pDestinationWidth); +HRESULT WINAPI BaseControlVideoImpl_put_DestinationTop(IBasicVideo *iface, LONG DestinationTop); +HRESULT WINAPI BaseControlVideoImpl_get_DestinationTop(IBasicVideo *iface, LONG *pDestinationTop); +HRESULT WINAPI BaseControlVideoImpl_put_DestinationHeight(IBasicVideo *iface, LONG DestinationHeight); +HRESULT WINAPI BaseControlVideoImpl_get_DestinationHeight(IBasicVideo *iface, LONG *pDestinationHeight); +HRESULT WINAPI BaseControlVideoImpl_SetSourcePosition(IBasicVideo *iface, LONG Left, LONG Top, LONG Width, LONG Height); +HRESULT WINAPI BaseControlVideoImpl_GetSourcePosition(IBasicVideo *iface, LONG *pLeft, LONG *pTop, LONG *pWidth, LONG *pHeight); +HRESULT WINAPI BaseControlVideoImpl_SetDefaultSourcePosition(IBasicVideo *iface); +HRESULT WINAPI BaseControlVideoImpl_SetDestinationPosition(IBasicVideo *iface, LONG Left, LONG Top, LONG Width, LONG Height); +HRESULT WINAPI BaseControlVideoImpl_GetDestinationPosition(IBasicVideo *iface, LONG *pLeft, LONG *pTop, LONG *pWidth, LONG *pHeight); +HRESULT WINAPI BaseControlVideoImpl_SetDefaultDestinationPosition(IBasicVideo *iface); +HRESULT WINAPI BaseControlVideoImpl_GetVideoSize(IBasicVideo *iface, LONG *pWidth, LONG *pHeight); +HRESULT WINAPI BaseControlVideoImpl_GetVideoPaletteEntries(IBasicVideo *iface, LONG StartIndex, LONG Entries, LONG *pRetrieved, LONG *pPalette); +HRESULT WINAPI BaseControlVideoImpl_GetCurrentImage(IBasicVideo *iface, LONG *pBufferSize, LONG *pDIBImage); +HRESULT WINAPI BaseControlVideoImpl_IsUsingDefaultSource(IBasicVideo *iface); +HRESULT WINAPI BaseControlVideoImpl_IsUsingDefaultDestination(IBasicVideo *iface); +#endif +#endif + +/* BaseRenderer Filter */ +typedef struct BaseRendererTag +{ + BaseFilter filter; + + BaseInputPin *pInputPin; + IUnknown *pPosition; + CRITICAL_SECTION csRenderLock; + HANDLE evComplete; + HANDLE ThreadSignal; + HANDLE RenderEvent; + IMediaSample *pMediaSample; + + IQualityControl *pQSink; + struct QualityControlImpl *qcimpl; + + const struct BaseRendererFuncTable * pFuncsTable; +} BaseRenderer; + +typedef HRESULT (WINAPI *BaseRenderer_CheckMediaType)(BaseRenderer *This, const AM_MEDIA_TYPE *pmt); +typedef HRESULT (WINAPI *BaseRenderer_DoRenderSample)(BaseRenderer *This, IMediaSample *pMediaSample); +typedef VOID (WINAPI *BaseRenderer_OnReceiveFirstSample)(BaseRenderer *This, IMediaSample *pMediaSample); +typedef VOID (WINAPI *BaseRenderer_OnRenderEnd)(BaseRenderer *This, IMediaSample *pMediaSample); +typedef VOID (WINAPI *BaseRenderer_OnRenderStart)(BaseRenderer *This, IMediaSample *pMediaSample); +typedef VOID (WINAPI *BaseRenderer_OnStartStreaming)(BaseRenderer *This); +typedef VOID (WINAPI *BaseRenderer_OnStopStreaming)(BaseRenderer *This); +typedef VOID (WINAPI *BaseRenderer_OnWaitEnd)(BaseRenderer *This); +typedef VOID (WINAPI *BaseRenderer_OnWaitStart)(BaseRenderer *This); +typedef VOID (WINAPI *BaseRenderer_PrepareRender)(BaseRenderer *This); +typedef HRESULT (WINAPI *BaseRenderer_ShouldDrawSampleNow)(BaseRenderer *This, IMediaSample *pMediaSample, REFERENCE_TIME *pStartTime, REFERENCE_TIME *pEndTime); +typedef HRESULT (WINAPI *BaseRenderer_PrepareReceive)(BaseRenderer *This, IMediaSample *pMediaSample); +typedef HRESULT (WINAPI *BaseRenderer_EndOfStream)(BaseRenderer *This); +typedef HRESULT (WINAPI *BaseRenderer_BeginFlush) (BaseRenderer *This); +typedef HRESULT (WINAPI *BaseRenderer_EndFlush) (BaseRenderer *This); +typedef HRESULT (WINAPI *BaseRenderer_BreakConnect) (BaseRenderer *This); +typedef HRESULT (WINAPI *BaseRenderer_CompleteConnect) (BaseRenderer *This, IPin *pReceivePin); + +typedef struct BaseRendererFuncTable { + /* Required */ + BaseRenderer_CheckMediaType pfnCheckMediaType; + BaseRenderer_DoRenderSample pfnDoRenderSample; + /* Optional, Data Handlers */ + BaseRenderer_OnReceiveFirstSample pfnOnReceiveFirstSample; + BaseRenderer_OnRenderEnd pfnOnRenderEnd; + BaseRenderer_OnRenderStart pfnOnRenderStart; + BaseRenderer_OnStartStreaming pfnOnStartStreaming; + BaseRenderer_OnStopStreaming pfnOnStopStreaming; + BaseRenderer_OnWaitEnd pfnOnWaitEnd; + BaseRenderer_OnWaitStart pfnOnWaitStart; + BaseRenderer_PrepareRender pfnPrepareRender; + BaseRenderer_ShouldDrawSampleNow pfnShouldDrawSampleNow; + BaseRenderer_PrepareReceive pfnPrepareReceive; + /* Optional, Input Pin */ + BaseRenderer_CompleteConnect pfnCompleteConnect; + BaseRenderer_BreakConnect pfnBreakConnect; + BaseRenderer_EndOfStream pfnEndOfStream; + BaseRenderer_BeginFlush pfnBeginFlush; + BaseRenderer_EndFlush pfnEndFlush; +} BaseRendererFuncTable; + +HRESULT WINAPI BaseRendererImpl_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv); +ULONG WINAPI BaseRendererImpl_Release(IBaseFilter * iface); +HRESULT WINAPI BaseRendererImpl_Receive(BaseRenderer *This, IMediaSample * pSample); +HRESULT WINAPI BaseRendererImpl_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin); +HRESULT WINAPI BaseRendererImpl_Stop(IBaseFilter * iface); +HRESULT WINAPI BaseRendererImpl_Run(IBaseFilter * iface, REFERENCE_TIME tStart); +HRESULT WINAPI BaseRendererImpl_Pause(IBaseFilter * iface); +HRESULT WINAPI BaseRendererImpl_SetSyncSource(IBaseFilter *iface, IReferenceClock *clock); +HRESULT WINAPI BaseRendererImpl_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState); +HRESULT WINAPI BaseRendererImpl_EndOfStream(BaseRenderer* iface); +HRESULT WINAPI BaseRendererImpl_BeginFlush(BaseRenderer* iface); +HRESULT WINAPI BaseRendererImpl_EndFlush(BaseRenderer* iface); +HRESULT WINAPI BaseRendererImpl_ClearPendingSample(BaseRenderer *iface); + +HRESULT WINAPI BaseRenderer_Init(BaseRenderer *This, const IBaseFilterVtbl *Vtbl, IUnknown *pUnkOuter, const CLSID *pClsid, DWORD_PTR DebugInfo, const BaseRendererFuncTable* pBaseFuncsTable); + +#ifdef __IBasicAudio_FWD_DEFINED__ +typedef struct tagBasicAudio +{ + IBasicAudio IBasicAudio_iface; + BaseDispatch baseDispatch; +} BasicAudio; + +HRESULT WINAPI BasicAudio_Init(BasicAudio *This, const IBasicAudioVtbl *Vtbl); +HRESULT WINAPI BasicAudio_Destroy(BasicAudio *pBasicAudio); + +HRESULT WINAPI BasicAudioImpl_GetTypeInfoCount(IBasicAudio *iface, UINT*pctinfo); +HRESULT WINAPI BasicAudioImpl_GetTypeInfo(IBasicAudio *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo); +HRESULT WINAPI BasicAudioImpl_GetIDsOfNames(IBasicAudio *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId); +HRESULT WINAPI BasicAudioImpl_Invoke(IBasicAudio *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo, UINT *puArgErr); +#endif + +/* Dll Functions */ +BOOL WINAPI STRMBASE_DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv); +HRESULT WINAPI STRMBASE_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv); +HRESULT WINAPI STRMBASE_DllCanUnloadNow(void); diff --git a/reactos/lib/3rdparty/CMakeLists.txt b/reactos/lib/3rdparty/CMakeLists.txt index 3526e3c26d8..52f1f933537 100644 --- a/reactos/lib/3rdparty/CMakeLists.txt +++ b/reactos/lib/3rdparty/CMakeLists.txt @@ -10,4 +10,5 @@ add_subdirectory(libsamplerate) add_subdirectory(libwine) add_subdirectory(libxml2) # add_subdirectory(stlport) FIXME: Add proper STL support +add_subdirectory(strmbase) add_subdirectory(zlib) diff --git a/reactos/lib/3rdparty/strmbase/CMakeLists.txt b/reactos/lib/3rdparty/strmbase/CMakeLists.txt new file mode 100644 index 00000000000..b8ec39a1cc6 --- /dev/null +++ b/reactos/lib/3rdparty/strmbase/CMakeLists.txt @@ -0,0 +1,23 @@ + +include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine) +add_definitions(-D__WINESRC__) + +list(APPEND SOURCE + audio.c + dispatch.c + dllfunc.c + enumpins.c + filter.c + mediatype.c + outputqueue.c + pin.c + pospass.c + qualitycontrol.c + renderer.c + seeking.c + transform.c + video.c + window.c) + +add_library(strmbase ${SOURCE}) +add_dependencies(strmbase psdk dxsdk) diff --git a/reactos/lib/3rdparty/strmbase/audio.c b/reactos/lib/3rdparty/strmbase/audio.c new file mode 100644 index 00000000000..e167a794019 --- /dev/null +++ b/reactos/lib/3rdparty/strmbase/audio.c @@ -0,0 +1,84 @@ +/* + * Generic Implementation of strmbase audio classes + * + * Copyright 2012 Aric Stewart, CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include +#include "dshow.h" +#include "uuids.h" +#include "vfwmsgs.h" +#include "wine/unicode.h" +#include "wine/strmbase.h" + + +static inline BasicAudio *impl_from_IBasicAudio(IBasicAudio *iface) +{ + return CONTAINING_RECORD(iface, BasicAudio, IBasicAudio_iface); +} + +HRESULT WINAPI BasicAudio_Init(BasicAudio *pBasicAudio, const IBasicAudioVtbl *lpVtbl) +{ + pBasicAudio->IBasicAudio_iface.lpVtbl = lpVtbl; + BaseDispatch_Init(&pBasicAudio->baseDispatch, &IID_IBasicAudio); + + return S_OK; +} + +HRESULT WINAPI BasicAudio_Destroy(BasicAudio *pBasicAudio) +{ + return BaseDispatch_Destroy(&pBasicAudio->baseDispatch); +} + +HRESULT WINAPI BasicAudioImpl_GetTypeInfoCount(IBasicAudio *iface, UINT *pctinfo) +{ + BasicAudio *This = impl_from_IBasicAudio(iface); + + return BaseDispatchImpl_GetTypeInfoCount(&This->baseDispatch, pctinfo); +} + +HRESULT WINAPI BasicAudioImpl_GetTypeInfo(IBasicAudio *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) +{ + BasicAudio *This = impl_from_IBasicAudio(iface); + + return BaseDispatchImpl_GetTypeInfo(&This->baseDispatch, &IID_NULL, iTInfo, lcid, ppTInfo); +} + +HRESULT WINAPI BasicAudioImpl_GetIDsOfNames(IBasicAudio *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) +{ + BasicAudio *This = impl_from_IBasicAudio(iface); + + return BaseDispatchImpl_GetIDsOfNames(&This->baseDispatch, riid, rgszNames, cNames, lcid, rgDispId); +} + +HRESULT WINAPI BasicAudioImpl_Invoke(IBasicAudio *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo, UINT *puArgErr) +{ + BasicAudio *This = impl_from_IBasicAudio(iface); + HRESULT hr = S_OK; + ITypeInfo *pTypeInfo; + + hr = BaseDispatchImpl_GetTypeInfo(&This->baseDispatch, riid, 1, lcid, &pTypeInfo); + if (SUCCEEDED(hr)) + { + hr = ITypeInfo_Invoke(pTypeInfo, &This->IBasicAudio_iface, dispIdMember, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr); + ITypeInfo_Release(pTypeInfo); + } + + return hr; +} diff --git a/reactos/lib/3rdparty/strmbase/dispatch.c b/reactos/lib/3rdparty/strmbase/dispatch.c new file mode 100644 index 00000000000..8f7aa058b17 --- /dev/null +++ b/reactos/lib/3rdparty/strmbase/dispatch.c @@ -0,0 +1,79 @@ +/* + * Generic Implementation of IDispatch for strmbase classes + * + * Copyright 2012 Aric Stewart, CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include "dshow.h" +#include "wine/unicode.h" +#include "wine/strmbase.h" +#include "uuids.h" +#include "vfwmsgs.h" +#include + +HRESULT WINAPI BaseDispatch_Init(BaseDispatch *This, REFIID riid) +{ + HRESULT hr = E_FAIL; + ITypeLib *pTypeLib; + + This->pTypeInfo = NULL; + hr = LoadRegTypeLib(&LIBID_QuartzTypeLib, 1, 0, LOCALE_SYSTEM_DEFAULT, &pTypeLib); + if (SUCCEEDED(hr)) + { + hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, riid, &This->pTypeInfo); + + if (pTypeLib) + ITypeLib_Release(pTypeLib); + } + return hr; +} + +HRESULT WINAPI BaseDispatch_Destroy(BaseDispatch *This) +{ + if (This->pTypeInfo) + ITypeInfo_Release(This->pTypeInfo); + return S_OK; +} + +HRESULT WINAPI BaseDispatchImpl_GetIDsOfNames(BaseDispatch *This, REFIID riid, OLECHAR **rgszNames, UINT cNames, LCID lcid, DISPID *rgdispid) +{ + if (This->pTypeInfo) + return ITypeInfo_GetIDsOfNames(This->pTypeInfo, rgszNames, cNames, rgdispid); + return E_NOTIMPL; +} + +HRESULT WINAPI BaseDispatchImpl_GetTypeInfo(BaseDispatch *This, REFIID riid, UINT itinfo, LCID lcid, ITypeInfo **pptinfo) +{ + if (This->pTypeInfo) + { + ITypeInfo_AddRef(This->pTypeInfo); + *pptinfo = This->pTypeInfo; + return S_OK; + } + return E_NOTIMPL; +} + +HRESULT WINAPI BaseDispatchImpl_GetTypeInfoCount(BaseDispatch *This, UINT *pctinfo) +{ + if (This->pTypeInfo) + *pctinfo = 1; + else + *pctinfo = 0; + return S_OK; +} diff --git a/reactos/lib/3rdparty/strmbase/dllfunc.c b/reactos/lib/3rdparty/strmbase/dllfunc.c new file mode 100644 index 00000000000..23e71db4743 --- /dev/null +++ b/reactos/lib/3rdparty/strmbase/dllfunc.c @@ -0,0 +1,469 @@ +/* + * Strmbase DLL functions + * + * Copyright (C) 2005 Rolf Kalbermatter + * Copyright (C) 2010 Aric Stewart, CodeWeavers +* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#include "config.h" + +#include +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winerror.h" +#include "winreg.h" +#include "objbase.h" +#include "uuids.h" +#include "strmif.h" + +#include "wine/unicode.h" +#include "wine/debug.h" +#include "wine/strmbase.h" + +WINE_DEFAULT_DEBUG_CHANNEL(strmbase); + +extern const int g_cTemplates; +extern const FactoryTemplate g_Templates[]; + +static HINSTANCE g_hInst = NULL; +static LONG server_locks = 0; + +/* + * defines and constants + */ +#define MAX_KEY_LEN 260 + +static const WCHAR clsid_keyname[] = {'C','L','S','I','D',0 }; +static const WCHAR ips32_keyname[] = {'I','n','P','r','o','c','S','e','r','v','e','r','3','2',0}; +static const WCHAR tmodel_keyname[] = {'T','h','r','e','a','d','i','n','g','M','o','d','e','l',0}; +static const WCHAR tmodel_both[] = {'B','o','t','h',0}; + +#ifdef __REACTOS__ +static LSTATUS WINAPI RegDeleteTreeW(HKEY hKey, LPCWSTR lpszSubKey) +{ + LONG ret; + DWORD dwMaxSubkeyLen, dwMaxValueLen; + DWORD dwMaxLen, dwSize; + WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf; + HKEY hSubKey = hKey; + + TRACE("(hkey=%p,%p %s)\n", hKey, lpszSubKey, debugstr_w(lpszSubKey)); + + if(lpszSubKey) + { + ret = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey); + if (ret) return ret; + } + + /* Get highest length for keys, values */ + ret = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL, + &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL); + if (ret) goto cleanup; + + dwMaxSubkeyLen++; + dwMaxValueLen++; + dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen); + if (dwMaxLen > sizeof(szNameBuf)/sizeof(WCHAR)) + { + /* Name too big: alloc a buffer for it */ + if (!(lpszName = HeapAlloc( GetProcessHeap(), 0, dwMaxLen*sizeof(WCHAR)))) + { + ret = ERROR_NOT_ENOUGH_MEMORY; + goto cleanup; + } + } + + + /* Recursively delete all the subkeys */ + while (TRUE) + { + dwSize = dwMaxLen; + if (RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL, + NULL, NULL, NULL)) break; + + ret = RegDeleteTreeW(hSubKey, lpszName); + if (ret) goto cleanup; + } + + if (lpszSubKey) + ret = RegDeleteKeyW(hKey, lpszSubKey); + else + while (TRUE) + { + dwSize = dwMaxLen; + if (RegEnumValueW(hKey, 0, lpszName, &dwSize, + NULL, NULL, NULL, NULL)) break; + + ret = RegDeleteValueW(hKey, lpszName); + if (ret) goto cleanup; + } + +cleanup: + /* Free buffer if allocated */ + if (lpszName != szNameBuf) + HeapFree( GetProcessHeap(), 0, lpszName); + if(lpszSubKey) + RegCloseKey(hSubKey); + return ret; +} +#endif + +/* + * SetupRegisterClass() + */ +static HRESULT SetupRegisterClass(HKEY clsid, LPCWSTR szCLSID, + LPCWSTR szDescription, + LPCWSTR szFileName, + LPCWSTR szServerType, + LPCWSTR szThreadingModel) +{ + HKEY hkey, hsubkey = NULL; + LONG ret = RegCreateKeyW(clsid, szCLSID, &hkey); + if (ERROR_SUCCESS != ret) + return HRESULT_FROM_WIN32(ret); + + /* set description string */ + ret = RegSetValueW(hkey, NULL, REG_SZ, szDescription, + sizeof(WCHAR) * (lstrlenW(szDescription) + 1)); + if (ERROR_SUCCESS != ret) + goto err_out; + + /* create CLSID\\{"CLSID"}\\"ServerType" key, using key to CLSID\\{"CLSID"} + passed back by last call to RegCreateKeyW(). */ + ret = RegCreateKeyW(hkey, szServerType, &hsubkey); + if (ERROR_SUCCESS != ret) + goto err_out; + + /* set server path */ + ret = RegSetValueW(hsubkey, NULL, REG_SZ, szFileName, + sizeof(WCHAR) * (lstrlenW(szFileName) + 1)); + if (ERROR_SUCCESS != ret) + goto err_out; + + /* set threading model */ + ret = RegSetValueExW(hsubkey, tmodel_keyname, 0L, REG_SZ, + (const BYTE*)szThreadingModel, + sizeof(WCHAR) * (lstrlenW(szThreadingModel) + 1)); +err_out: + if (hsubkey) + RegCloseKey(hsubkey); + RegCloseKey(hkey); + return HRESULT_FROM_WIN32(ret); +} + +/* + * RegisterAllClasses() + */ +static HRESULT SetupRegisterAllClasses(const FactoryTemplate * pList, int num, + LPCWSTR szFileName, BOOL bRegister) +{ + HRESULT hr = NOERROR; + HKEY hkey; + OLECHAR szCLSID[CHARS_IN_GUID]; + LONG i, ret = RegCreateKeyW(HKEY_CLASSES_ROOT, clsid_keyname, &hkey); + if (ERROR_SUCCESS != ret) + return HRESULT_FROM_WIN32(ret); + + for (i = 0; i < num; i++, pList++) + { + /* (un)register CLSID and InprocServer32 */ + hr = StringFromGUID2(pList->m_ClsID, szCLSID, CHARS_IN_GUID); + if (SUCCEEDED(hr)) + { + if (bRegister ) + hr = SetupRegisterClass(hkey, szCLSID, + pList->m_Name, szFileName, + ips32_keyname, tmodel_both); + else + hr = RegDeleteTreeW(hkey, szCLSID); + } + } + RegCloseKey(hkey); + return hr; +} + +HRESULT WINAPI AMovieSetupRegisterFilter2(const AMOVIESETUP_FILTER *pFilter, IFilterMapper2 *pIFM2, BOOL bRegister) +{ + if (!pFilter) + return S_OK; + + if (bRegister) + { + { + REGFILTER2 rf2; + rf2.dwVersion = 1; + rf2.dwMerit = pFilter->merit; + rf2.cPins = pFilter->pins; + rf2.rgPins = pFilter->pPin; + + return IFilterMapper2_RegisterFilter(pIFM2, pFilter->clsid, pFilter->name, NULL, &CLSID_LegacyAmFilterCategory, NULL, &rf2); + } + } + else + return IFilterMapper2_UnregisterFilter(pIFM2, &CLSID_LegacyAmFilterCategory, NULL, pFilter->clsid); +} + +HRESULT WINAPI AMovieDllRegisterServer2(BOOL bRegister) +{ + HRESULT hr; + int i; + IFilterMapper2 *pIFM2 = NULL; + WCHAR szFileName[MAX_PATH]; + + if (!GetModuleFileNameW(g_hInst, szFileName, MAX_PATH)) + { + ERR("Failed to get module file name for registration\n"); + return E_FAIL; + } + + if (bRegister) + hr = SetupRegisterAllClasses(g_Templates, g_cTemplates, szFileName, TRUE ); + + hr = CoInitialize(NULL); + + TRACE("Getting IFilterMapper2\r\n"); + hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, + &IID_IFilterMapper2, (void **)&pIFM2); + + for (i = 0; SUCCEEDED(hr) && i < g_cTemplates; i++) + hr = AMovieSetupRegisterFilter2(g_Templates[i].m_pAMovieSetup_Filter, pIFM2, bRegister); + + /* release interface */ + if (pIFM2) + IFilterMapper2_Release(pIFM2); + + /* and clear up */ + CoFreeUnusedLibraries(); + CoUninitialize(); + + /* if unregistering, unregister all OLE servers */ + if (SUCCEEDED(hr) && !bRegister) + hr = SetupRegisterAllClasses(g_Templates, g_cTemplates, szFileName, FALSE); + + return hr; +} + +/**************************************************************************** + * SetupInitializeServers + * + * This function is table driven using the static members of the + * CFactoryTemplate class defined in the Dll. + * + * It calls the initialize function for any class in CFactoryTemplate with + * one defined. + * + ****************************************************************************/ +static void SetupInitializeServers(const FactoryTemplate * pList, int num, + BOOL bLoading) +{ + int i; + + for (i = 0; i < num; i++, pList++) + { + if (pList->m_lpfnInit) + pList->m_lpfnInit(bLoading, pList->m_ClsID); + } +} + +BOOL WINAPI STRMBASE_DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) +{ + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + g_hInst = hInstDLL; + DisableThreadLibraryCalls(hInstDLL); + SetupInitializeServers(g_Templates, g_cTemplates, TRUE); + break; + case DLL_PROCESS_DETACH: + SetupInitializeServers(g_Templates, g_cTemplates, FALSE); + break; + } + return TRUE; +} + +/****************************************************************************** + * DLL ClassFactory + */ +typedef struct { + IClassFactory IClassFactory_iface; + LONG ref; + LPFNNewCOMObject pfnCreateInstance; +} IClassFactoryImpl; + +static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface) +{ + return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface); +} + +static HRESULT WINAPI DSCF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj) +{ + if (IsEqualGUID(riid, &IID_IUnknown) || + IsEqualGUID(riid, &IID_IClassFactory)) + { + IClassFactory_AddRef(iface); + *ppobj = iface; + return S_OK; + } + + *ppobj = NULL; + WARN("(%p)->(%s,%p), not found\n", iface, debugstr_guid(riid), ppobj); + return E_NOINTERFACE; +} + +static ULONG WINAPI DSCF_AddRef(IClassFactory *iface) +{ + IClassFactoryImpl *This = impl_from_IClassFactory(iface); + return InterlockedIncrement(&This->ref); +} + +static ULONG WINAPI DSCF_Release(IClassFactory *iface) +{ + IClassFactoryImpl *This = impl_from_IClassFactory(iface); + ULONG ref = InterlockedDecrement(&This->ref); + + if (ref == 0) + HeapFree(GetProcessHeap(), 0, This); + + return ref; +} + +static HRESULT WINAPI DSCF_CreateInstance(IClassFactory *iface, IUnknown *pOuter, + REFIID riid, void **ppobj) +{ + IClassFactoryImpl *This = impl_from_IClassFactory(iface); + HRESULT hres = ERROR_SUCCESS; + LPUNKNOWN punk; + + TRACE("(%p)->(%p,%s,%p)\n", This, pOuter, debugstr_guid(riid), ppobj); + + if (!ppobj) + return E_POINTER; + + /* Enforce the normal OLE rules regarding interfaces and delegation */ + if (pOuter && !IsEqualGUID(riid, &IID_IUnknown)) + return E_NOINTERFACE; + + *ppobj = NULL; + punk = This->pfnCreateInstance(pOuter, &hres); + if (!punk) + { + /* No object created, update error if it isn't done already and return */ + if (SUCCEEDED(hres)) + hres = E_OUTOFMEMORY; + return hres; + } + + if (SUCCEEDED(hres)) + { + hres = IUnknown_QueryInterface(punk, riid, ppobj); + } + /* Releasing the object. If everything was successful, QueryInterface + should have incremented the refcount once more, otherwise this will + purge the object. */ + IUnknown_Release(punk); + return hres; +} + +static HRESULT WINAPI DSCF_LockServer(IClassFactory *iface, BOOL dolock) +{ + IClassFactoryImpl *This = impl_from_IClassFactory(iface); + TRACE("(%p)->(%d)\n",This, dolock); + + if (dolock) + InterlockedIncrement(&server_locks); + else + InterlockedDecrement(&server_locks); + return S_OK; +} + +static const IClassFactoryVtbl DSCF_Vtbl = +{ + DSCF_QueryInterface, + DSCF_AddRef, + DSCF_Release, + DSCF_CreateInstance, + DSCF_LockServer +}; + +/*********************************************************************** + * DllGetClassObject + */ +HRESULT WINAPI STRMBASE_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) +{ + const FactoryTemplate *pList = g_Templates; + IClassFactoryImpl *factory; + int i; + + TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); + + if (!ppv) + return E_POINTER; + + *ppv = NULL; + + if (!IsEqualGUID(&IID_IClassFactory, riid) && + !IsEqualGUID(&IID_IUnknown, riid)) + return E_NOINTERFACE; + + for (i = 0; i < g_cTemplates; i++, pList++) + { + if (IsEqualGUID(pList->m_ClsID, rclsid)) + break; + } + + if (i == g_cTemplates) + { + char dllname[MAX_PATH]; + if (!GetModuleFileNameA(g_hInst, dllname, sizeof(dllname))) + strcpy(dllname, "???"); + ERR("%s: no class found in %s.\n", debugstr_guid(rclsid), dllname); + return CLASS_E_CLASSNOTAVAILABLE; + } + else if (!pList->m_lpfnNew) + { + FIXME("%s: class not implemented yet.\n", debugstr_guid(rclsid)); + return CLASS_E_CLASSNOTAVAILABLE; + } + + factory = HeapAlloc(GetProcessHeap(), 0, sizeof(IClassFactoryImpl)); + if (!factory) + return E_OUTOFMEMORY; + + factory->IClassFactory_iface.lpVtbl = &DSCF_Vtbl; + factory->ref = 1; + + factory->pfnCreateInstance = pList->m_lpfnNew; + + *ppv = &factory->IClassFactory_iface; + return S_OK; +} + +/*********************************************************************** + * DllCanUnloadNow + */ +HRESULT WINAPI STRMBASE_DllCanUnloadNow(void) +{ + TRACE("\n"); + + if (server_locks == 0) + return S_OK; + return S_FALSE; +} diff --git a/reactos/dll/directx/quartz/enumpins.c b/reactos/lib/3rdparty/strmbase/enumpins.c similarity index 63% rename from reactos/dll/directx/quartz/enumpins.c rename to reactos/lib/3rdparty/strmbase/enumpins.c index 7f3c6440df5..eab4d5b0e8a 100644 --- a/reactos/dll/directx/quartz/enumpins.c +++ b/reactos/lib/3rdparty/strmbase/enumpins.c @@ -2,6 +2,7 @@ * Implementation of IEnumPins Interface * * Copyright 2003 Robert Shearman + * Copyright 2010 Aric Stewart, CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,25 +19,34 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include "quartz_private.h" +#define COBJMACROS -#include +#include "dshow.h" +#include "wine/strmbase.h" +#include "wine/debug.h" -WINE_DEFAULT_DEBUG_CHANNEL(quartz); +WINE_DEFAULT_DEBUG_CHANNEL(strmbase); typedef struct IEnumPinsImpl { - const IEnumPinsVtbl * lpVtbl; + IEnumPins IEnumPins_iface; LONG refCount; ULONG uIndex; - IBaseFilter *base; - FNOBTAINPIN receive_pin; - DWORD synctime; + BaseFilter *base; + BaseFilter_GetPin receive_pin; + BaseFilter_GetPinCount receive_pincount; + BaseFilter_GetPinVersion receive_version; + DWORD Version; } IEnumPinsImpl; +static inline IEnumPinsImpl *impl_from_IEnumPins(IEnumPins *iface) +{ + return CONTAINING_RECORD(iface, IEnumPinsImpl, IEnumPins_iface); +} + static const struct IEnumPinsVtbl IEnumPinsImpl_Vtbl; -HRESULT IEnumPinsImpl_Construct(IEnumPins ** ppEnum, FNOBTAINPIN receive_pin, IBaseFilter *base) +HRESULT WINAPI EnumPins_Construct(BaseFilter *base, BaseFilter_GetPin receive_pin, BaseFilter_GetPinCount receive_pincount, BaseFilter_GetPinVersion receive_version, IEnumPins ** ppEnum) { IEnumPinsImpl * pEnumPins; @@ -49,15 +59,16 @@ HRESULT IEnumPinsImpl_Construct(IEnumPins ** ppEnum, FNOBTAINPIN receive_pin, IB *ppEnum = NULL; return E_OUTOFMEMORY; } - pEnumPins->lpVtbl = &IEnumPinsImpl_Vtbl; + pEnumPins->IEnumPins_iface.lpVtbl = &IEnumPinsImpl_Vtbl; pEnumPins->refCount = 1; pEnumPins->uIndex = 0; pEnumPins->receive_pin = receive_pin; + pEnumPins->receive_pincount = receive_pincount; + pEnumPins->receive_version = receive_version; pEnumPins->base = base; - IBaseFilter_AddRef(base); - *ppEnum = (IEnumPins *)(&pEnumPins->lpVtbl); - - receive_pin(base, ~0, NULL, &pEnumPins->synctime); + IBaseFilter_AddRef(&base->IBaseFilter_iface); + *ppEnum = &pEnumPins->IEnumPins_iface; + pEnumPins->Version = receive_version(base); TRACE("Created new enumerator (%p)\n", *ppEnum); return S_OK; @@ -65,7 +76,7 @@ HRESULT IEnumPinsImpl_Construct(IEnumPins ** ppEnum, FNOBTAINPIN receive_pin, IB static HRESULT WINAPI IEnumPinsImpl_QueryInterface(IEnumPins * iface, REFIID riid, LPVOID * ppv) { - TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv); + TRACE("(%s, %p)\n", debugstr_guid(riid), ppv); *ppv = NULL; @@ -80,14 +91,14 @@ static HRESULT WINAPI IEnumPinsImpl_QueryInterface(IEnumPins * iface, REFIID rii return S_OK; } - FIXME("No interface for %s!\n", qzdebugstr_guid(riid)); + FIXME("No interface for %s!\n", debugstr_guid(riid)); return E_NOINTERFACE; } static ULONG WINAPI IEnumPinsImpl_AddRef(IEnumPins * iface) { - IEnumPinsImpl *This = (IEnumPinsImpl *)iface; + IEnumPinsImpl *This = impl_from_IEnumPins(iface); ULONG refCount = InterlockedIncrement(&This->refCount); TRACE("(%p)->() AddRef from %d\n", This, refCount - 1); @@ -97,14 +108,14 @@ static ULONG WINAPI IEnumPinsImpl_AddRef(IEnumPins * iface) static ULONG WINAPI IEnumPinsImpl_Release(IEnumPins * iface) { - IEnumPinsImpl *This = (IEnumPinsImpl *)iface; + IEnumPinsImpl *This = impl_from_IEnumPins(iface); ULONG refCount = InterlockedDecrement(&This->refCount); TRACE("(%p)->() Release from %d\n", This, refCount + 1); if (!refCount) { - IBaseFilter_Release(This->base); + IBaseFilter_Release(&This->base->IBaseFilter_iface); CoTaskMemFree(This); return 0; } @@ -114,8 +125,7 @@ static ULONG WINAPI IEnumPinsImpl_Release(IEnumPins * iface) static HRESULT WINAPI IEnumPinsImpl_Next(IEnumPins * iface, ULONG cPins, IPin ** ppPins, ULONG * pcFetched) { - IEnumPinsImpl *This = (IEnumPinsImpl *)iface; - DWORD synctime = This->synctime; + IEnumPinsImpl *This = impl_from_IEnumPins(iface); HRESULT hr = S_OK; ULONG i = 0; @@ -130,20 +140,21 @@ static HRESULT WINAPI IEnumPinsImpl_Next(IEnumPins * iface, ULONG cPins, IPin ** if (pcFetched) *pcFetched = 0; + if (This->Version != This->receive_version(This->base)) + return VFW_E_ENUM_OUT_OF_SYNC; + while (i < cPins && hr == S_OK) { - hr = This->receive_pin(This->base, This->uIndex + i, &ppPins[i], &synctime); + IPin *pin; + pin = This->receive_pin(This->base, This->uIndex + i); - if (hr == S_OK) - ++i; - - if (synctime != This->synctime) - break; + if (!pin) + break; + else + ppPins[i] = pin; + ++i; } - if (!i && synctime != This->synctime) - return VFW_E_ENUM_OUT_OF_SYNC; - if (pcFetched) *pcFetched = i; This->uIndex += i; @@ -155,32 +166,26 @@ static HRESULT WINAPI IEnumPinsImpl_Next(IEnumPins * iface, ULONG cPins, IPin ** static HRESULT WINAPI IEnumPinsImpl_Skip(IEnumPins * iface, ULONG cPins) { - IEnumPinsImpl *This = (IEnumPinsImpl *)iface; - DWORD synctime = This->synctime; - HRESULT hr; - IPin *pin = NULL; + IEnumPinsImpl *This = impl_from_IEnumPins(iface); TRACE("(%u)\n", cPins); - hr = This->receive_pin(This->base, This->uIndex + cPins, &pin, &synctime); - if (pin) - IPin_Release(pin); - - if (synctime != This->synctime) + if (This->Version != This->receive_version(This->base)) return VFW_E_ENUM_OUT_OF_SYNC; - if (hr == S_OK) - This->uIndex += cPins; + if (This->receive_pincount(This->base) >= This->uIndex + cPins) + return S_FALSE; - return hr; + This->uIndex += cPins; + return S_OK; } static HRESULT WINAPI IEnumPinsImpl_Reset(IEnumPins * iface) { - IEnumPinsImpl *This = (IEnumPinsImpl *)iface; + IEnumPinsImpl *This = impl_from_IEnumPins(iface); TRACE("IEnumPinsImpl::Reset()\n"); - This->receive_pin(This->base, ~0, NULL, &This->synctime); + This->Version = This->receive_version(This->base); This->uIndex = 0; return S_OK; @@ -189,11 +194,11 @@ static HRESULT WINAPI IEnumPinsImpl_Reset(IEnumPins * iface) static HRESULT WINAPI IEnumPinsImpl_Clone(IEnumPins * iface, IEnumPins ** ppEnum) { HRESULT hr; - IEnumPinsImpl *This = (IEnumPinsImpl *)iface; + IEnumPinsImpl *This = impl_from_IEnumPins(iface); TRACE("(%p)\n", ppEnum); - hr = IEnumPinsImpl_Construct(ppEnum, This->receive_pin, This->base); + hr = EnumPins_Construct(This->base, This->receive_pin, This->receive_pincount, This->receive_version, ppEnum); if (FAILED(hr)) return hr; return IEnumPins_Skip(*ppEnum, This->uIndex); diff --git a/reactos/lib/3rdparty/strmbase/filter.c b/reactos/lib/3rdparty/strmbase/filter.c new file mode 100644 index 00000000000..67f7c9ff226 --- /dev/null +++ b/reactos/lib/3rdparty/strmbase/filter.c @@ -0,0 +1,228 @@ +/* + * Generic Implementation of IBaseFilter Interface + * + * Copyright 2010 Aric Stewart, CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include "dshow.h" +#include "wine/debug.h" +#include "wine/unicode.h" +#include "wine/strmbase.h" +#include "uuids.h" +#include + +WINE_DEFAULT_DEBUG_CHANNEL(strmbase); + +static inline BaseFilter *impl_from_IBaseFilter(IBaseFilter *iface) +{ + return CONTAINING_RECORD(iface, BaseFilter, IBaseFilter_iface); +} + +HRESULT WINAPI BaseFilterImpl_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv) +{ + BaseFilter *This = impl_from_IBaseFilter(iface); + TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv); + + *ppv = NULL; + + if (IsEqualIID(riid, &IID_IUnknown)) + *ppv = This; + else if (IsEqualIID(riid, &IID_IPersist)) + *ppv = This; + else if (IsEqualIID(riid, &IID_IMediaFilter)) + *ppv = This; + else if (IsEqualIID(riid, &IID_IBaseFilter)) + *ppv = This; + + if (*ppv) + { + IUnknown_AddRef((IUnknown *)(*ppv)); + return S_OK; + } + + return E_NOINTERFACE; +} + +ULONG WINAPI BaseFilterImpl_AddRef(IBaseFilter * iface) +{ + BaseFilter *This = impl_from_IBaseFilter(iface); + ULONG refCount = InterlockedIncrement(&This->refCount); + + TRACE("(%p)->() AddRef from %d\n", This, refCount - 1); + + return refCount; +} + +ULONG WINAPI BaseFilterImpl_Release(IBaseFilter * iface) +{ + BaseFilter *This = impl_from_IBaseFilter(iface); + ULONG refCount = InterlockedDecrement(&This->refCount); + + TRACE("(%p)->() Release from %d\n", This, refCount + 1); + + if (!refCount) + { + if (This->pClock) + IReferenceClock_Release(This->pClock); + + This->IBaseFilter_iface.lpVtbl = NULL; + This->csFilter.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&This->csFilter); + } + + return refCount; +} + +HRESULT WINAPI BaseFilterImpl_GetClassID(IBaseFilter * iface, CLSID * pClsid) +{ + BaseFilter *This = impl_from_IBaseFilter(iface); + TRACE("(%p)->(%p)\n", This, pClsid); + + *pClsid = This->clsid; + + return S_OK; +} + +HRESULT WINAPI BaseFilterImpl_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState ) +{ + BaseFilter *This = impl_from_IBaseFilter(iface); + TRACE("(%p)->(%d, %p)\n", This, dwMilliSecsTimeout, pState); + + EnterCriticalSection(&This->csFilter); + { + *pState = This->state; + } + LeaveCriticalSection(&This->csFilter); + + return S_OK; +} + +HRESULT WINAPI BaseFilterImpl_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock) +{ + BaseFilter *This = impl_from_IBaseFilter(iface); + TRACE("(%p)->(%p)\n", This, pClock); + + EnterCriticalSection(&This->csFilter); + { + if (This->pClock) + IReferenceClock_Release(This->pClock); + This->pClock = pClock; + if (This->pClock) + IReferenceClock_AddRef(This->pClock); + } + LeaveCriticalSection(&This->csFilter); + + return S_OK; +} + +HRESULT WINAPI BaseFilterImpl_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock) +{ + BaseFilter *This = impl_from_IBaseFilter(iface); + TRACE("(%p)->(%p)\n", This, ppClock); + + EnterCriticalSection(&This->csFilter); + { + *ppClock = This->pClock; + if (This->pClock) + IReferenceClock_AddRef(This->pClock); + } + LeaveCriticalSection(&This->csFilter); + + return S_OK; +} + +HRESULT WINAPI BaseFilterImpl_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum) +{ + BaseFilter *This = impl_from_IBaseFilter(iface); + + TRACE("(%p)->(%p)\n", iface, ppEnum); + + return EnumPins_Construct(This, This->pFuncsTable->pfnGetPin, This->pFuncsTable->pfnGetPinCount, BaseFilterImpl_GetPinVersion, ppEnum); +} + + +HRESULT WINAPI BaseFilterImpl_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo) +{ + BaseFilter *This = impl_from_IBaseFilter(iface); + TRACE("(%p)->(%p)\n", This, pInfo); + + strcpyW(pInfo->achName, This->filterInfo.achName); + pInfo->pGraph = This->filterInfo.pGraph; + + if (pInfo->pGraph) + IFilterGraph_AddRef(pInfo->pGraph); + + return S_OK; +} + +HRESULT WINAPI BaseFilterImpl_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName ) +{ + HRESULT hr = S_OK; + BaseFilter *This = impl_from_IBaseFilter(iface); + + TRACE("(%p)->(%p, %s)\n", This, pGraph, debugstr_w(pName)); + + EnterCriticalSection(&This->csFilter); + { + if (pName) + strcpyW(This->filterInfo.achName, pName); + else + *This->filterInfo.achName = '\0'; + This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */ + } + LeaveCriticalSection(&This->csFilter); + + return hr; +} + +HRESULT WINAPI BaseFilterImpl_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo) +{ + TRACE("(%p)->(%p)\n", iface, pVendorInfo); + return E_NOTIMPL; +} + +LONG WINAPI BaseFilterImpl_GetPinVersion(BaseFilter * This) +{ + TRACE("(%p)\n", This); + return This->pinVersion; +} + +VOID WINAPI BaseFilterImpl_IncrementPinVersion(BaseFilter * This) +{ + InterlockedIncrement(&This->pinVersion); + TRACE("(%p) -> New pinVersion %i\n", This,This->pinVersion); +} + +HRESULT WINAPI BaseFilter_Init(BaseFilter * This, const IBaseFilterVtbl *Vtbl, const CLSID *pClsid, DWORD_PTR DebugInfo, const BaseFilterFuncTable* pBaseFuncsTable) +{ + This->IBaseFilter_iface.lpVtbl = Vtbl; + This->refCount = 1; + InitializeCriticalSection(&This->csFilter); + This->state = State_Stopped; + This->rtStreamStart = 0; + This->pClock = NULL; + ZeroMemory(&This->filterInfo, sizeof(FILTER_INFO)); + This->clsid = *pClsid; + This->csFilter.DebugInfo->Spare[0] = DebugInfo; + This->pinVersion = 1; + + This->pFuncsTable = pBaseFuncsTable; + + return S_OK; +} diff --git a/reactos/lib/3rdparty/strmbase/mediatype.c b/reactos/lib/3rdparty/strmbase/mediatype.c new file mode 100644 index 00000000000..d100cc9e8c9 --- /dev/null +++ b/reactos/lib/3rdparty/strmbase/mediatype.c @@ -0,0 +1,307 @@ +/* + * Implementation of MedaType utility functions + * + * Copyright 2003 Robert Shearman + * Copyright 2010 Aric Stewart, CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#include + +#define COBJMACROS +#include "dshow.h" + +#include "wine/strmbase.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(strmbase); + +HRESULT WINAPI CopyMediaType(AM_MEDIA_TYPE *dest, const AM_MEDIA_TYPE *src) +{ + *dest = *src; + if (src->pbFormat) + { + dest->pbFormat = CoTaskMemAlloc(src->cbFormat); + if (!dest->pbFormat) + return E_OUTOFMEMORY; + memcpy(dest->pbFormat, src->pbFormat, src->cbFormat); + } + if (dest->pUnk) + IUnknown_AddRef(dest->pUnk); + return S_OK; +} + +void WINAPI FreeMediaType(AM_MEDIA_TYPE * pMediaType) +{ + if (pMediaType->pbFormat) + { + CoTaskMemFree(pMediaType->pbFormat); + pMediaType->pbFormat = NULL; + } + if (pMediaType->pUnk) + { + IUnknown_Release(pMediaType->pUnk); + pMediaType->pUnk = NULL; + } +} + +AM_MEDIA_TYPE * WINAPI CreateMediaType(AM_MEDIA_TYPE const * pSrc) +{ + AM_MEDIA_TYPE * pDest; + + pDest = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE)); + if (!pDest) + return NULL; + + if (FAILED(CopyMediaType(pDest, pSrc))) + { + CoTaskMemFree(pDest); + return NULL; + } + + return pDest; +} + +void WINAPI DeleteMediaType(AM_MEDIA_TYPE * pMediaType) +{ + FreeMediaType(pMediaType); + CoTaskMemFree(pMediaType); +} + +typedef struct tagENUMEDIADETAILS +{ + ULONG cMediaTypes; + AM_MEDIA_TYPE * pMediaTypes; +} ENUMMEDIADETAILS; + +typedef struct IEnumMediaTypesImpl +{ + IEnumMediaTypes IEnumMediaTypes_iface; + LONG refCount; + BasePin *basePin; + BasePin_GetMediaType enumMediaFunction; + BasePin_GetMediaTypeVersion mediaVersionFunction; + LONG currentVersion; + ENUMMEDIADETAILS enumMediaDetails; + ULONG uIndex; +} IEnumMediaTypesImpl; + +static inline IEnumMediaTypesImpl *impl_from_IEnumMediaTypes(IEnumMediaTypes *iface) +{ + return CONTAINING_RECORD(iface, IEnumMediaTypesImpl, IEnumMediaTypes_iface); +} + +static const struct IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl; + +HRESULT WINAPI EnumMediaTypes_Construct(BasePin *basePin, BasePin_GetMediaType enumFunc, BasePin_GetMediaTypeVersion versionFunc, IEnumMediaTypes ** ppEnum) +{ + ULONG i; + IEnumMediaTypesImpl * pEnumMediaTypes = CoTaskMemAlloc(sizeof(IEnumMediaTypesImpl)); + AM_MEDIA_TYPE amt; + + if (!pEnumMediaTypes) + { + *ppEnum = NULL; + return E_OUTOFMEMORY; + } + pEnumMediaTypes->IEnumMediaTypes_iface.lpVtbl = &IEnumMediaTypesImpl_Vtbl; + pEnumMediaTypes->refCount = 1; + pEnumMediaTypes->uIndex = 0; + pEnumMediaTypes->enumMediaFunction = enumFunc; + pEnumMediaTypes->mediaVersionFunction = versionFunc; + IPin_AddRef(&basePin->IPin_iface); + pEnumMediaTypes->basePin = basePin; + + i = 0; + while (enumFunc(basePin, i, &amt) == S_OK) i++; + + pEnumMediaTypes->enumMediaDetails.cMediaTypes = i; + pEnumMediaTypes->enumMediaDetails.pMediaTypes = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * i); + for (i = 0; i < pEnumMediaTypes->enumMediaDetails.cMediaTypes; i++) + { + enumFunc(basePin,i,&amt); + if (FAILED(CopyMediaType(&pEnumMediaTypes->enumMediaDetails.pMediaTypes[i], &amt))) + { + while (i--) + FreeMediaType(&pEnumMediaTypes->enumMediaDetails.pMediaTypes[i]); + CoTaskMemFree(pEnumMediaTypes->enumMediaDetails.pMediaTypes); + return E_OUTOFMEMORY; + } + } + *ppEnum = &pEnumMediaTypes->IEnumMediaTypes_iface; + pEnumMediaTypes->currentVersion = versionFunc(basePin); + return S_OK; +} + +static HRESULT WINAPI IEnumMediaTypesImpl_QueryInterface(IEnumMediaTypes * iface, REFIID riid, void ** ret_iface) +{ + TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ret_iface); + + if (IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IEnumMediaTypes)) + { + IEnumMediaTypes_AddRef(iface); + *ret_iface = iface; + return S_OK; + } + + *ret_iface = NULL; + + WARN("No interface for %s\n", debugstr_guid(riid)); + + return E_NOINTERFACE; +} + +static ULONG WINAPI IEnumMediaTypesImpl_AddRef(IEnumMediaTypes * iface) +{ + IEnumMediaTypesImpl *This = impl_from_IEnumMediaTypes(iface); + ULONG ref = InterlockedIncrement(&This->refCount); + + TRACE("(%p)->(): new ref = %u\n", iface, ref); + + return ref; +} + +static ULONG WINAPI IEnumMediaTypesImpl_Release(IEnumMediaTypes * iface) +{ + IEnumMediaTypesImpl *This = impl_from_IEnumMediaTypes(iface); + ULONG ref = InterlockedDecrement(&This->refCount); + + TRACE("(%p)->(): new ref = %u\n", iface, ref); + + if (!ref) + { + ULONG i; + for (i = 0; i < This->enumMediaDetails.cMediaTypes; i++) + FreeMediaType(&This->enumMediaDetails.pMediaTypes[i]); + CoTaskMemFree(This->enumMediaDetails.pMediaTypes); + IPin_Release(&This->basePin->IPin_iface); + CoTaskMemFree(This); + } + return ref; +} + +static HRESULT WINAPI IEnumMediaTypesImpl_Next(IEnumMediaTypes * iface, ULONG cMediaTypes, AM_MEDIA_TYPE ** ppMediaTypes, ULONG * pcFetched) +{ + ULONG cFetched; + IEnumMediaTypesImpl *This = impl_from_IEnumMediaTypes(iface); + + TRACE("(%p)->(%u, %p, %p)\n", iface, cMediaTypes, ppMediaTypes, pcFetched); + + cFetched = min(This->enumMediaDetails.cMediaTypes, This->uIndex + cMediaTypes) - This->uIndex; + + if (This->currentVersion != This->mediaVersionFunction(This->basePin)) + return VFW_E_ENUM_OUT_OF_SYNC; + + TRACE("Next uIndex: %u, cFetched: %u\n", This->uIndex, cFetched); + + if (cFetched > 0) + { + ULONG i; + for (i = 0; i < cFetched; i++) + if (!(ppMediaTypes[i] = CreateMediaType(&This->enumMediaDetails.pMediaTypes[This->uIndex + i]))) + { + while (i--) + DeleteMediaType(ppMediaTypes[i]); + *pcFetched = 0; + return E_OUTOFMEMORY; + } + } + + if ((cMediaTypes != 1) || pcFetched) + *pcFetched = cFetched; + + This->uIndex += cFetched; + + if (cFetched != cMediaTypes) + return S_FALSE; + return S_OK; +} + +static HRESULT WINAPI IEnumMediaTypesImpl_Skip(IEnumMediaTypes * iface, ULONG cMediaTypes) +{ + IEnumMediaTypesImpl *This = impl_from_IEnumMediaTypes(iface); + + TRACE("(%p)->(%u)\n", iface, cMediaTypes); + + if (This->currentVersion != This->mediaVersionFunction(This->basePin)) + return VFW_E_ENUM_OUT_OF_SYNC; + + if (This->uIndex + cMediaTypes < This->enumMediaDetails.cMediaTypes) + { + This->uIndex += cMediaTypes; + return S_OK; + } + return S_FALSE; +} + +static HRESULT WINAPI IEnumMediaTypesImpl_Reset(IEnumMediaTypes * iface) +{ + ULONG i; + AM_MEDIA_TYPE amt; + IEnumMediaTypesImpl *This = impl_from_IEnumMediaTypes(iface); + + TRACE("(%p)->()\n", iface); + + for (i = 0; i < This->enumMediaDetails.cMediaTypes; i++) + FreeMediaType(&This->enumMediaDetails.pMediaTypes[i]); + CoTaskMemFree(This->enumMediaDetails.pMediaTypes); + + i = 0; + while (This->enumMediaFunction(This->basePin, i, &amt) == S_OK) i++; + + This->enumMediaDetails.cMediaTypes = i; + This->enumMediaDetails.pMediaTypes = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * i); + for (i = 0; i < This->enumMediaDetails.cMediaTypes; i++) + { + This->enumMediaFunction(This->basePin, i,&amt); + if (FAILED(CopyMediaType(&This->enumMediaDetails.pMediaTypes[i], &amt))) + { + while (i--) + FreeMediaType(&This->enumMediaDetails.pMediaTypes[i]); + CoTaskMemFree(This->enumMediaDetails.pMediaTypes); + return E_OUTOFMEMORY; + } + } + + This->currentVersion = This->mediaVersionFunction(This->basePin); + This->uIndex = 0; + + return S_OK; +} + +static HRESULT WINAPI IEnumMediaTypesImpl_Clone(IEnumMediaTypes * iface, IEnumMediaTypes ** ppEnum) +{ + HRESULT hr; + IEnumMediaTypesImpl *This = impl_from_IEnumMediaTypes(iface); + + TRACE("(%p)->(%p)\n", iface, ppEnum); + + hr = EnumMediaTypes_Construct(This->basePin, This->enumMediaFunction, This->mediaVersionFunction, ppEnum); + if (FAILED(hr)) + return hr; + return IEnumMediaTypes_Skip(*ppEnum, This->uIndex); +} + +static const IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl = +{ + IEnumMediaTypesImpl_QueryInterface, + IEnumMediaTypesImpl_AddRef, + IEnumMediaTypesImpl_Release, + IEnumMediaTypesImpl_Next, + IEnumMediaTypesImpl_Skip, + IEnumMediaTypesImpl_Reset, + IEnumMediaTypesImpl_Clone +}; diff --git a/reactos/lib/3rdparty/strmbase/outputqueue.c b/reactos/lib/3rdparty/strmbase/outputqueue.c new file mode 100644 index 00000000000..cbcd9640766 --- /dev/null +++ b/reactos/lib/3rdparty/strmbase/outputqueue.c @@ -0,0 +1,310 @@ +/* + * Generic Implementation of COutputQueue + * + * Copyright 2011 Aric Stewart, CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include "dshow.h" +#include "wine/debug.h" +#include "wine/unicode.h" +#include "wine/list.h" +#include "wine/strmbase.h" +#include "uuids.h" +#include "vfwmsgs.h" +#include + +WINE_DEFAULT_DEBUG_CHANNEL(strmbase); + +enum {SAMPLE_PACKET, EOS_PACKET}; + +typedef struct tagQueuedEvent { + int type; + struct list entry; + + IMediaSample *pSample; +} QueuedEvent; + +static DWORD WINAPI OutputQueue_InitialThreadProc(LPVOID data) +{ + OutputQueue *This = (OutputQueue *)data; + return This->pFuncsTable->pfnThreadProc(This); +} + +static void OutputQueue_FreeSamples(OutputQueue *pOutputQueue) +{ + struct list *cursor, *cursor2; + LIST_FOR_EACH_SAFE(cursor, cursor2, pOutputQueue->SampleList) + { + QueuedEvent *qev = LIST_ENTRY(cursor, QueuedEvent, entry); + list_remove(cursor); + HeapFree(GetProcessHeap(),0,qev); + } +} + +HRESULT WINAPI OutputQueue_Construct( + BaseOutputPin *pInputPin, + BOOL bAuto, + BOOL bQueue, + LONG lBatchSize, + BOOL bBatchExact, + DWORD dwPriority, + const OutputQueueFuncTable* pFuncsTable, + OutputQueue **ppOutputQueue ) + +{ + HRESULT hr = S_OK; + BOOL threaded = FALSE; + DWORD tid; + + OutputQueue *This; + + if (!pInputPin || !pFuncsTable || !ppOutputQueue) + return E_INVALIDARG; + + *ppOutputQueue = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(OutputQueue)); + if (!*ppOutputQueue) + return E_OUTOFMEMORY; + + This = *ppOutputQueue; + This->pFuncsTable = pFuncsTable; + This->lBatchSize = lBatchSize; + This->bBatchExact = bBatchExact; + InitializeCriticalSection(&This->csQueue); + This->csQueue.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": OutputQueue.csQueue"); + This->SampleList = HeapAlloc(GetProcessHeap(),0,sizeof(struct list)); + if (!This->SampleList) + { + OutputQueue_Destroy(This); + *ppOutputQueue = NULL; + return E_OUTOFMEMORY; + } + list_init(This->SampleList); + + This->pInputPin = pInputPin; + IPin_AddRef(&pInputPin->pin.IPin_iface); + + EnterCriticalSection(&This->csQueue); + if (bAuto && pInputPin->pMemInputPin) + threaded = IMemInputPin_ReceiveCanBlock(pInputPin->pMemInputPin); + else + threaded = bQueue; + + if (threaded) + { + This->hThread = CreateThread(NULL, 0, OutputQueue_InitialThreadProc, This, 0, &tid); + if (This->hThread) + { + SetThreadPriority(This->hThread, dwPriority); + This->hProcessQueue = CreateEventW(NULL, 0, 0, NULL); + } + } + LeaveCriticalSection(&This->csQueue); + + return hr; +} + +HRESULT WINAPI OutputQueue_Destroy(OutputQueue *pOutputQueue) +{ + EnterCriticalSection(&pOutputQueue->csQueue); + OutputQueue_FreeSamples(pOutputQueue); + pOutputQueue->bTerminate = TRUE; + SetEvent(pOutputQueue->hProcessQueue); + LeaveCriticalSection(&pOutputQueue->csQueue); + + pOutputQueue->csQueue.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&pOutputQueue->csQueue); + CloseHandle(pOutputQueue->hProcessQueue); + + HeapFree(GetProcessHeap(),0,pOutputQueue->SampleList); + + IPin_Release(&pOutputQueue->pInputPin->pin.IPin_iface); + HeapFree(GetProcessHeap(),0,pOutputQueue); + return S_OK; +} + +HRESULT WINAPI OutputQueue_ReceiveMultiple(OutputQueue *pOutputQueue, IMediaSample **ppSamples, LONG nSamples, LONG *nSamplesProcessed) +{ + HRESULT hr = S_OK; + int i; + + if (!pOutputQueue->pInputPin->pin.pConnectedTo || !pOutputQueue->pInputPin->pMemInputPin) + return VFW_E_NOT_CONNECTED; + + if (!pOutputQueue->hThread) + { + IMemInputPin_AddRef(pOutputQueue->pInputPin->pMemInputPin); + hr = IMemInputPin_ReceiveMultiple(pOutputQueue->pInputPin->pMemInputPin,ppSamples, nSamples, nSamplesProcessed); + IMemInputPin_Release(pOutputQueue->pInputPin->pMemInputPin); + } + else + { + EnterCriticalSection(&pOutputQueue->csQueue); + *nSamplesProcessed = 0; + + for (i = 0; i < nSamples; i++) + { + QueuedEvent *qev = HeapAlloc(GetProcessHeap(),0,sizeof(QueuedEvent)); + if (!qev) + { + ERR("Out of Memory\n"); + hr = E_OUTOFMEMORY; + break; + } + qev->type = SAMPLE_PACKET; + qev->pSample = ppSamples[i]; + IMediaSample_AddRef(ppSamples[i]); + list_add_tail(pOutputQueue->SampleList, &qev->entry); + (*nSamplesProcessed)++; + } + + if (!pOutputQueue->bBatchExact || list_count(pOutputQueue->SampleList) >= pOutputQueue->lBatchSize) + SetEvent(pOutputQueue->hProcessQueue); + LeaveCriticalSection(&pOutputQueue->csQueue); + } + return hr; +} + +HRESULT WINAPI OutputQueue_Receive(OutputQueue *pOutputQueue, IMediaSample *pSample) +{ + LONG processed; + return OutputQueue_ReceiveMultiple(pOutputQueue,&pSample,1,&processed); +} + +VOID WINAPI OutputQueue_SendAnyway(OutputQueue *pOutputQueue) +{ + if (pOutputQueue->hThread) + { + EnterCriticalSection(&pOutputQueue->csQueue); + if (!list_empty(pOutputQueue->SampleList)) + { + pOutputQueue->bSendAnyway = TRUE; + SetEvent(pOutputQueue->hProcessQueue); + } + LeaveCriticalSection(&pOutputQueue->csQueue); + } +} + +VOID WINAPI OutputQueue_EOS(OutputQueue *pOutputQueue) +{ + EnterCriticalSection(&pOutputQueue->csQueue); + if (pOutputQueue->hThread) + { + QueuedEvent *qev = HeapAlloc(GetProcessHeap(),0,sizeof(QueuedEvent)); + if (!qev) + { + ERR("Out of Memory\n"); + LeaveCriticalSection(&pOutputQueue->csQueue); + return; + } + qev->type = EOS_PACKET; + qev->pSample = NULL; + list_add_tail(pOutputQueue->SampleList, &qev->entry); + } + else + { + IPin* ppin = NULL; + IPin_ConnectedTo(&pOutputQueue->pInputPin->pin.IPin_iface, &ppin); + if (ppin) + { + IPin_EndOfStream(ppin); + IPin_Release(ppin); + } + } + LeaveCriticalSection(&pOutputQueue->csQueue); + /* Covers sending the Event to the worker Thread */ + OutputQueue_SendAnyway(pOutputQueue); +} + +DWORD WINAPI OutputQueueImpl_ThreadProc(OutputQueue *pOutputQueue) +{ + do + { + EnterCriticalSection(&pOutputQueue->csQueue); + if (!list_empty(pOutputQueue->SampleList) && + (!pOutputQueue->bBatchExact || + list_count(pOutputQueue->SampleList) >= pOutputQueue->lBatchSize || + pOutputQueue->bSendAnyway + ) + ) + { + while (!list_empty(pOutputQueue->SampleList)) + { + IMediaSample **ppSamples; + LONG nSamples; + LONG nSamplesProcessed; + struct list *cursor, *cursor2; + int i = 0; + + /* First Pass Process Samples */ + i = list_count(pOutputQueue->SampleList); + ppSamples = HeapAlloc(GetProcessHeap(),0,sizeof(IMediaSample*) * i); + nSamples = 0; + LIST_FOR_EACH_SAFE(cursor, cursor2, pOutputQueue->SampleList) + { + QueuedEvent *qev = LIST_ENTRY(cursor, QueuedEvent, entry); + if (qev->type == SAMPLE_PACKET) + ppSamples[nSamples++] = qev->pSample; + else + break; + list_remove(cursor); + HeapFree(GetProcessHeap(),0,qev); + } + + if (pOutputQueue->pInputPin->pin.pConnectedTo && pOutputQueue->pInputPin->pMemInputPin) + { + IMemInputPin_AddRef(pOutputQueue->pInputPin->pMemInputPin); + LeaveCriticalSection(&pOutputQueue->csQueue); + IMemInputPin_ReceiveMultiple(pOutputQueue->pInputPin->pMemInputPin, ppSamples, nSamples, &nSamplesProcessed); + EnterCriticalSection(&pOutputQueue->csQueue); + IMemInputPin_Release(pOutputQueue->pInputPin->pMemInputPin); + } + for (i = 0; i < nSamples; i++) + IMediaSample_Release(ppSamples[i]); + HeapFree(GetProcessHeap(),0,ppSamples); + + /* Process Non-Samples */ + LIST_FOR_EACH_SAFE(cursor, cursor2, pOutputQueue->SampleList) + { + QueuedEvent *qev = LIST_ENTRY(cursor, QueuedEvent, entry); + if (qev->type == EOS_PACKET) + { + IPin* ppin = NULL; + IPin_ConnectedTo(&pOutputQueue->pInputPin->pin.IPin_iface, &ppin); + if (ppin) + { + IPin_EndOfStream(ppin); + IPin_Release(ppin); + } + } + else if (qev->type == SAMPLE_PACKET) + break; + else + FIXME("Unhandled Event type %i\n",qev->type); + list_remove(cursor); + HeapFree(GetProcessHeap(),0,qev); + } + } + pOutputQueue->bSendAnyway = FALSE; + } + LeaveCriticalSection(&pOutputQueue->csQueue); + WaitForSingleObject(pOutputQueue->hProcessQueue, INFINITE); + } + while (!pOutputQueue->bTerminate); + return S_OK; +} diff --git a/reactos/lib/3rdparty/strmbase/pin.c b/reactos/lib/3rdparty/strmbase/pin.c new file mode 100644 index 00000000000..750752e733e --- /dev/null +++ b/reactos/lib/3rdparty/strmbase/pin.c @@ -0,0 +1,1269 @@ +/* + * Generic Implementation of IPin Interface + * + * Copyright 2003 Robert Shearman + * Copyright 2010 Aric Stewart, CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include "dshow.h" +#include "wine/debug.h" +#include "wine/unicode.h" +#include "wine/strmbase.h" +#include "uuids.h" +#include "vfwmsgs.h" +#include + +WINE_DEFAULT_DEBUG_CHANNEL(strmbase); + +static const IPinVtbl InputPin_Vtbl; +static const IPinVtbl OutputPin_Vtbl; +static const IMemInputPinVtbl MemInputPin_Vtbl; + +typedef HRESULT (*SendPinFunc)( IPin *to, LPVOID arg ); + +static inline BasePin *impl_from_IPin( IPin *iface ) +{ + return CONTAINING_RECORD(iface, BasePin, IPin_iface); +} + +/** Helper function, there are a lot of places where the error code is inherited + * The following rules apply: + * + * Return the first received error code (E_NOTIMPL is ignored) + * If no errors occur: return the first received non-error-code that isn't S_OK + */ +static HRESULT updatehres( HRESULT original, HRESULT new ) +{ + if (FAILED( original ) || new == E_NOTIMPL) + return original; + + if (FAILED( new ) || original == S_OK) + return new; + + return original; +} + +/** Sends a message from a pin further to other, similar pins + * fnMiddle is called on each pin found further on the stream. + * fnEnd (can be NULL) is called when the message can't be sent any further (this is a renderer or source) + * + * If the pin given is an input pin, the message will be sent downstream to other input pins + * If the pin given is an output pin, the message will be sent upstream to other output pins + */ +static HRESULT SendFurther( IPin *from, SendPinFunc fnMiddle, LPVOID arg, SendPinFunc fnEnd ) +{ + PIN_INFO pin_info; + ULONG amount = 0; + HRESULT hr = S_OK; + HRESULT hr_return = S_OK; + IEnumPins *enumpins = NULL; + BOOL foundend = TRUE; + PIN_DIRECTION from_dir; + + IPin_QueryDirection( from, &from_dir ); + + hr = IPin_QueryInternalConnections( from, NULL, &amount ); + if (hr != E_NOTIMPL && amount) + FIXME("Use QueryInternalConnections!\n"); + hr = S_OK; + + pin_info.pFilter = NULL; + hr = IPin_QueryPinInfo( from, &pin_info ); + if (FAILED(hr)) + goto out; + + hr = IBaseFilter_EnumPins( pin_info.pFilter, &enumpins ); + if (FAILED(hr)) + goto out; + + hr = IEnumPins_Reset( enumpins ); + while (hr == S_OK) { + IPin *pin = NULL; + hr = IEnumPins_Next( enumpins, 1, &pin, NULL ); + if (hr == VFW_E_ENUM_OUT_OF_SYNC) + { + hr = IEnumPins_Reset( enumpins ); + continue; + } + if (pin) + { + PIN_DIRECTION dir; + + IPin_QueryDirection( pin, &dir ); + if (dir != from_dir) + { + IPin *connected = NULL; + + foundend = FALSE; + IPin_ConnectedTo( pin, &connected ); + if (connected) + { + HRESULT hr_local; + + hr_local = fnMiddle( connected, arg ); + hr_return = updatehres( hr_return, hr_local ); + IPin_Release(connected); + } + } + IPin_Release( pin ); + } + else + { + hr = S_OK; + break; + } + } + + if (!foundend) + hr = hr_return; + else if (fnEnd) { + HRESULT hr_local; + + hr_local = fnEnd( from, arg ); + hr_return = updatehres( hr_return, hr_local ); + } + IEnumPins_Release(enumpins); + +out: + if (pin_info.pFilter) + IBaseFilter_Release( pin_info.pFilter ); + return hr; +} + +static void Copy_PinInfo(PIN_INFO * pDest, const PIN_INFO * pSrc) +{ + /* Tempting to just do a memcpy, but the name field is + 128 characters long! We will probably never exceed 10 + most of the time, so we are better off copying + each field manually */ + strcpyW(pDest->achName, pSrc->achName); + pDest->dir = pSrc->dir; + pDest->pFilter = pSrc->pFilter; +} + +static void dump_AM_MEDIA_TYPE(const AM_MEDIA_TYPE * pmt) +{ + if (!pmt) + return; + TRACE("\t%s\n\t%s\n\t...\n\t%s\n", debugstr_guid(&pmt->majortype), debugstr_guid(&pmt->subtype), debugstr_guid(&pmt->formattype)); +} + +static BOOL CompareMediaTypes(const AM_MEDIA_TYPE * pmt1, const AM_MEDIA_TYPE * pmt2, BOOL bWildcards) +{ + TRACE("pmt1: "); + dump_AM_MEDIA_TYPE(pmt1); + TRACE("pmt2: "); + dump_AM_MEDIA_TYPE(pmt2); + return (((bWildcards && (IsEqualGUID(&pmt1->majortype, &GUID_NULL) || IsEqualGUID(&pmt2->majortype, &GUID_NULL))) || IsEqualGUID(&pmt1->majortype, &pmt2->majortype)) && + ((bWildcards && (IsEqualGUID(&pmt1->subtype, &GUID_NULL) || IsEqualGUID(&pmt2->subtype, &GUID_NULL))) || IsEqualGUID(&pmt1->subtype, &pmt2->subtype))); +} + +/*** Common Base Pin function */ +HRESULT WINAPI BasePinImpl_GetMediaType(BasePin *iface, int iPosition, AM_MEDIA_TYPE *pmt) +{ + if (iPosition < 0) + return E_INVALIDARG; + return VFW_S_NO_MORE_ITEMS; +} + +LONG WINAPI BasePinImpl_GetMediaTypeVersion(BasePin *iface) +{ + return 1; +} + +ULONG WINAPI BasePinImpl_AddRef(IPin * iface) +{ + BasePin *This = impl_from_IPin(iface); + ULONG refCount = InterlockedIncrement(&This->refCount); + + TRACE("(%p)->() AddRef from %d\n", iface, refCount - 1); + + return refCount; +} + +HRESULT WINAPI BasePinImpl_Disconnect(IPin * iface) +{ + HRESULT hr; + BasePin *This = impl_from_IPin(iface); + + TRACE("()\n"); + + EnterCriticalSection(This->pCritSec); + { + if (This->pConnectedTo) + { + IPin_Release(This->pConnectedTo); + This->pConnectedTo = NULL; + FreeMediaType(&This->mtCurrent); + ZeroMemory(&This->mtCurrent, sizeof(This->mtCurrent)); + hr = S_OK; + } + else + hr = S_FALSE; + } + LeaveCriticalSection(This->pCritSec); + + return hr; +} + +HRESULT WINAPI BasePinImpl_ConnectedTo(IPin * iface, IPin ** ppPin) +{ + HRESULT hr; + BasePin *This = impl_from_IPin(iface); + + TRACE("(%p)\n", ppPin); + + EnterCriticalSection(This->pCritSec); + { + if (This->pConnectedTo) + { + *ppPin = This->pConnectedTo; + IPin_AddRef(*ppPin); + hr = S_OK; + } + else + { + hr = VFW_E_NOT_CONNECTED; + *ppPin = NULL; + } + } + LeaveCriticalSection(This->pCritSec); + + return hr; +} + +HRESULT WINAPI BasePinImpl_ConnectionMediaType(IPin * iface, AM_MEDIA_TYPE * pmt) +{ + HRESULT hr; + BasePin *This = impl_from_IPin(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, pmt); + + EnterCriticalSection(This->pCritSec); + { + if (This->pConnectedTo) + { + CopyMediaType(pmt, &This->mtCurrent); + hr = S_OK; + } + else + { + ZeroMemory(pmt, sizeof(*pmt)); + hr = VFW_E_NOT_CONNECTED; + } + } + LeaveCriticalSection(This->pCritSec); + + return hr; +} + +HRESULT WINAPI BasePinImpl_QueryPinInfo(IPin * iface, PIN_INFO * pInfo) +{ + BasePin *This = impl_from_IPin(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, pInfo); + + Copy_PinInfo(pInfo, &This->pinInfo); + IBaseFilter_AddRef(pInfo->pFilter); + + return S_OK; +} + +HRESULT WINAPI BasePinImpl_QueryDirection(IPin * iface, PIN_DIRECTION * pPinDir) +{ + BasePin *This = impl_from_IPin(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, pPinDir); + + *pPinDir = This->pinInfo.dir; + + return S_OK; +} + +HRESULT WINAPI BasePinImpl_QueryId(IPin * iface, LPWSTR * Id) +{ + BasePin *This = impl_from_IPin(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, Id); + + *Id = CoTaskMemAlloc((strlenW(This->pinInfo.achName) + 1) * sizeof(WCHAR)); + if (!*Id) + return E_OUTOFMEMORY; + + strcpyW(*Id, This->pinInfo.achName); + + return S_OK; +} + +HRESULT WINAPI BasePinImpl_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt) +{ + TRACE("(%p)->(%p)\n", iface, pmt); + + return S_OK; +} + +HRESULT WINAPI BasePinImpl_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum) +{ + BasePin *This = impl_from_IPin(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum); + + /* override this method to allow enumeration of your types */ + + return EnumMediaTypes_Construct(This, This->pFuncsTable->pfnGetMediaType, This->pFuncsTable->pfnGetMediaTypeVersion , ppEnum); +} + +HRESULT WINAPI BasePinImpl_QueryInternalConnections(IPin * iface, IPin ** apPin, ULONG * cPin) +{ + BasePin *This = impl_from_IPin(iface); + + TRACE("(%p/%p)->(%p, %p)\n", This, iface, apPin, cPin); + + return E_NOTIMPL; /* to tell caller that all input pins connected to all output pins */ +} + +HRESULT WINAPI BasePinImpl_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) +{ + BasePin *This = impl_from_IPin(iface); + + TRACE("(%x%08x, %x%08x, %e)\n", (ULONG)(tStart >> 32), (ULONG)tStart, (ULONG)(tStop >> 32), (ULONG)tStop, dRate); + + This->tStart = tStart; + This->tStop = tStop; + This->dRate = dRate; + + return S_OK; +} + +/*** OutputPin implementation ***/ + +static inline BaseOutputPin *impl_BaseOutputPin_from_IPin( IPin *iface ) +{ + return CONTAINING_RECORD(iface, BaseOutputPin, pin.IPin_iface); +} + +static inline BaseOutputPin *impl_BaseOutputPin_from_BasePin( BasePin *iface ) +{ + return CONTAINING_RECORD(iface, BaseOutputPin, pin); +} + +HRESULT WINAPI BaseOutputPinImpl_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv) +{ + BaseOutputPin *This = impl_BaseOutputPin_from_IPin(iface); + + TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppv); + + *ppv = NULL; + + if (IsEqualIID(riid, &IID_IUnknown)) + *ppv = iface; + else if (IsEqualIID(riid, &IID_IPin)) + *ppv = iface; + else if (IsEqualIID(riid, &IID_IMediaSeeking) || + IsEqualIID(riid, &IID_IQualityControl)) + { + return IBaseFilter_QueryInterface(This->pin.pinInfo.pFilter, riid, ppv); + } + + if (*ppv) + { + IUnknown_AddRef((IUnknown *)(*ppv)); + return S_OK; + } + + FIXME("No interface for %s!\n", debugstr_guid(riid)); + + return E_NOINTERFACE; +} + +ULONG WINAPI BaseOutputPinImpl_Release(IPin * iface) +{ + BaseOutputPin *This = impl_BaseOutputPin_from_IPin(iface); + ULONG refCount = InterlockedDecrement(&This->pin.refCount); + + TRACE("(%p)->() Release from %d\n", iface, refCount + 1); + + if (!refCount) + { + FreeMediaType(&This->pin.mtCurrent); + if (This->pAllocator) + IMemAllocator_Release(This->pAllocator); + This->pAllocator = NULL; + CoTaskMemFree(This); + return 0; + } + return refCount; +} + +HRESULT WINAPI BaseOutputPinImpl_Connect(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) +{ + HRESULT hr; + BaseOutputPin *This = impl_BaseOutputPin_from_IPin(iface); + + TRACE("(%p/%p)->(%p, %p)\n", This, iface, pReceivePin, pmt); + dump_AM_MEDIA_TYPE(pmt); + + /* If we try to connect to ourselves, we will definitely deadlock. + * There are other cases where we could deadlock too, but this + * catches the obvious case */ + assert(pReceivePin != iface); + + EnterCriticalSection(This->pin.pCritSec); + { + /* if we have been a specific type to connect with, then we can either connect + * with that or fail. We cannot choose different AM_MEDIA_TYPE */ + if (pmt && !IsEqualGUID(&pmt->majortype, &GUID_NULL) && !IsEqualGUID(&pmt->subtype, &GUID_NULL)) + hr = This->pin.pFuncsTable->pfnAttemptConnection(&This->pin, pReceivePin, pmt); + else + { + /* negotiate media type */ + + IEnumMediaTypes * pEnumCandidates; + AM_MEDIA_TYPE * pmtCandidate = NULL; /* Candidate media type */ + + if (SUCCEEDED(hr = IPin_EnumMediaTypes(iface, &pEnumCandidates))) + { + hr = VFW_E_NO_ACCEPTABLE_TYPES; /* Assume the worst, but set to S_OK if connected successfully */ + + /* try this filter's media types first */ + while (S_OK == IEnumMediaTypes_Next(pEnumCandidates, 1, &pmtCandidate, NULL)) + { + assert(pmtCandidate); + dump_AM_MEDIA_TYPE(pmtCandidate); + if (!IsEqualGUID(&FORMAT_None, &pmtCandidate->formattype) + && !IsEqualGUID(&GUID_NULL, &pmtCandidate->formattype)) + assert(pmtCandidate->pbFormat); + if (( !pmt || CompareMediaTypes(pmt, pmtCandidate, TRUE) ) && + (This->pin.pFuncsTable->pfnAttemptConnection(&This->pin, pReceivePin, pmtCandidate) == S_OK)) + { + hr = S_OK; + DeleteMediaType(pmtCandidate); + break; + } + DeleteMediaType(pmtCandidate); + pmtCandidate = NULL; + } + IEnumMediaTypes_Release(pEnumCandidates); + } + + /* then try receiver filter's media types */ + if (hr != S_OK && SUCCEEDED(hr = IPin_EnumMediaTypes(pReceivePin, &pEnumCandidates))) /* if we haven't already connected successfully */ + { + hr = VFW_E_NO_ACCEPTABLE_TYPES; /* Assume the worst, but set to S_OK if connected successfully */ + + while (S_OK == IEnumMediaTypes_Next(pEnumCandidates, 1, &pmtCandidate, NULL)) + { + assert(pmtCandidate); + dump_AM_MEDIA_TYPE(pmtCandidate); + if (( !pmt || CompareMediaTypes(pmt, pmtCandidate, TRUE) ) && + (This->pin.pFuncsTable->pfnAttemptConnection(&This->pin, pReceivePin, pmtCandidate) == S_OK)) + { + hr = S_OK; + DeleteMediaType(pmtCandidate); + break; + } + DeleteMediaType(pmtCandidate); + pmtCandidate = NULL; + } /* while */ + IEnumMediaTypes_Release(pEnumCandidates); + } /* if not found */ + } /* if negotiate media type */ + } /* if succeeded */ + LeaveCriticalSection(This->pin.pCritSec); + + TRACE(" -- %x\n", hr); + return hr; +} + +HRESULT WINAPI BaseOutputPinImpl_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) +{ + ERR("Incoming connection on an output pin! (%p, %p)\n", pReceivePin, pmt); + + return E_UNEXPECTED; +} + +HRESULT WINAPI BaseOutputPinImpl_Disconnect(IPin * iface) +{ + HRESULT hr; + BaseOutputPin *This = impl_BaseOutputPin_from_IPin(iface); + + TRACE("()\n"); + + EnterCriticalSection(This->pin.pCritSec); + { + if (This->pMemInputPin) + { + IMemInputPin_Release(This->pMemInputPin); + This->pMemInputPin = NULL; + } + if (This->pin.pConnectedTo) + { + IPin_Release(This->pin.pConnectedTo); + This->pin.pConnectedTo = NULL; + FreeMediaType(&This->pin.mtCurrent); + ZeroMemory(&This->pin.mtCurrent, sizeof(This->pin.mtCurrent)); + hr = S_OK; + } + else + hr = S_FALSE; + } + LeaveCriticalSection(This->pin.pCritSec); + + return hr; +} + +HRESULT WINAPI BaseOutputPinImpl_EndOfStream(IPin * iface) +{ + TRACE("()\n"); + + /* not supposed to do anything in an output pin */ + + return E_UNEXPECTED; +} + +HRESULT WINAPI BaseOutputPinImpl_BeginFlush(IPin * iface) +{ + TRACE("(%p)->()\n", iface); + + /* not supposed to do anything in an output pin */ + + return E_UNEXPECTED; +} + +HRESULT WINAPI BaseOutputPinImpl_EndFlush(IPin * iface) +{ + TRACE("(%p)->()\n", iface); + + /* not supposed to do anything in an output pin */ + + return E_UNEXPECTED; +} + +static const IPinVtbl OutputPin_Vtbl = +{ + BaseOutputPinImpl_QueryInterface, + BasePinImpl_AddRef, + BaseOutputPinImpl_Release, + BaseOutputPinImpl_Connect, + BaseOutputPinImpl_ReceiveConnection, + BaseOutputPinImpl_Disconnect, + BasePinImpl_ConnectedTo, + BasePinImpl_ConnectionMediaType, + BasePinImpl_QueryPinInfo, + BasePinImpl_QueryDirection, + BasePinImpl_QueryId, + BasePinImpl_QueryAccept, + BasePinImpl_EnumMediaTypes, + BasePinImpl_QueryInternalConnections, + BaseOutputPinImpl_EndOfStream, + BaseOutputPinImpl_BeginFlush, + BaseOutputPinImpl_EndFlush, + BasePinImpl_NewSegment +}; + +HRESULT WINAPI BaseOutputPinImpl_GetDeliveryBuffer(BaseOutputPin *This, IMediaSample ** ppSample, REFERENCE_TIME * tStart, REFERENCE_TIME * tStop, DWORD dwFlags) +{ + HRESULT hr; + + TRACE("(%p, %p, %p, %x)\n", ppSample, tStart, tStop, dwFlags); + + if (!This->pin.pConnectedTo) + hr = VFW_E_NOT_CONNECTED; + else + { + hr = IMemAllocator_GetBuffer(This->pAllocator, ppSample, tStart, tStop, dwFlags); + + if (SUCCEEDED(hr)) + hr = IMediaSample_SetTime(*ppSample, tStart, tStop); + } + + return hr; +} + +/* replaces OutputPin_SendSample */ +HRESULT WINAPI BaseOutputPinImpl_Deliver(BaseOutputPin *This, IMediaSample * pSample) +{ + HRESULT hr = S_OK; + IMemInputPin * pMemConnected = NULL; + PIN_INFO pinInfo; + + EnterCriticalSection(This->pin.pCritSec); + { + if (!This->pin.pConnectedTo || !This->pMemInputPin) + hr = VFW_E_NOT_CONNECTED; + else + { + /* we don't have the lock held when using This->pMemInputPin, + * so we need to AddRef it to stop it being deleted while we are + * using it. Same with its filter. */ + pMemConnected = This->pMemInputPin; + IMemInputPin_AddRef(pMemConnected); + hr = IPin_QueryPinInfo(This->pin.pConnectedTo, &pinInfo); + } + } + LeaveCriticalSection(This->pin.pCritSec); + + if (SUCCEEDED(hr)) + { + /* NOTE: if we are in a critical section when Receive is called + * then it causes some problems (most notably with the native Video + * Renderer) if we are re-entered for whatever reason */ + hr = IMemInputPin_Receive(pMemConnected, pSample); + + /* If the filter's destroyed, tell upstream to stop sending data */ + if(IBaseFilter_Release(pinInfo.pFilter) == 0 && SUCCEEDED(hr)) + hr = S_FALSE; + } + if (pMemConnected) + IMemInputPin_Release(pMemConnected); + + return hr; +} + +/* replaces OutputPin_CommitAllocator */ +HRESULT WINAPI BaseOutputPinImpl_Active(BaseOutputPin *This) +{ + HRESULT hr = S_OK; + + TRACE("(%p)->()\n", This); + + EnterCriticalSection(This->pin.pCritSec); + { + if (!This->pin.pConnectedTo || !This->pMemInputPin) + hr = VFW_E_NOT_CONNECTED; + else + hr = IMemAllocator_Commit(This->pAllocator); + } + LeaveCriticalSection(This->pin.pCritSec); + + TRACE("--> %08x\n", hr); + return hr; +} + +/* replaces OutputPin_DecommitAllocator */ +HRESULT WINAPI BaseOutputPinImpl_Inactive(BaseOutputPin *This) +{ + HRESULT hr = S_OK; + + TRACE("(%p)->()\n", This); + + EnterCriticalSection(This->pin.pCritSec); + { + if (!This->pin.pConnectedTo || !This->pMemInputPin) + hr = VFW_E_NOT_CONNECTED; + else + hr = IMemAllocator_Decommit(This->pAllocator); + } + LeaveCriticalSection(This->pin.pCritSec); + + TRACE("--> %08x\n", hr); + return hr; +} + +/* replaces OutputPin_DeliverDisconnect */ +HRESULT WINAPI BaseOutputPinImpl_BreakConnect(BaseOutputPin *This) +{ + HRESULT hr; + + TRACE("(%p)->()\n", This); + + EnterCriticalSection(This->pin.pCritSec); + { + if (!This->pin.pConnectedTo || !This->pMemInputPin) + hr = VFW_E_NOT_CONNECTED; + else + { + hr = IMemAllocator_Decommit(This->pAllocator); + + if (SUCCEEDED(hr)) + hr = IPin_Disconnect(This->pin.pConnectedTo); + } + IPin_Disconnect(&This->pin.IPin_iface); + } + LeaveCriticalSection(This->pin.pCritSec); + + return hr; +} + +HRESULT WINAPI BaseOutputPinImpl_InitAllocator(BaseOutputPin *This, IMemAllocator **pMemAlloc) +{ + return CoCreateInstance(&CLSID_MemoryAllocator, NULL, CLSCTX_INPROC_SERVER, &IID_IMemAllocator, (LPVOID*)pMemAlloc); +} + +HRESULT WINAPI BaseOutputPinImpl_DecideAllocator(BaseOutputPin *This, IMemInputPin *pPin, IMemAllocator **pAlloc) +{ + HRESULT hr; + + hr = IMemInputPin_GetAllocator(pPin, pAlloc); + + if (hr == VFW_E_NO_ALLOCATOR) + /* Input pin provides no allocator, use standard memory allocator */ + hr = BaseOutputPinImpl_InitAllocator(This, pAlloc); + + if (SUCCEEDED(hr)) + { + ALLOCATOR_PROPERTIES rProps; + ZeroMemory(&rProps, sizeof(ALLOCATOR_PROPERTIES)); + + IMemInputPin_GetAllocatorRequirements(pPin, &rProps); + hr = This->pFuncsTable->pfnDecideBufferSize(This, *pAlloc, &rProps); + } + + if (SUCCEEDED(hr)) + hr = IMemInputPin_NotifyAllocator(pPin, *pAlloc, FALSE); + + return hr; +} + +/*** The Construct functions ***/ + +/* Function called as a helper to IPin_Connect */ +/* specific AM_MEDIA_TYPE - it cannot be NULL */ +HRESULT WINAPI BaseOutputPinImpl_AttemptConnection(BasePin* iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) +{ + BaseOutputPin *This = impl_BaseOutputPin_from_BasePin(iface); + HRESULT hr; + IMemAllocator * pMemAlloc = NULL; + + TRACE("(%p, %p)\n", pReceivePin, pmt); + dump_AM_MEDIA_TYPE(pmt); + + /* FIXME: call queryacceptproc */ + + This->pin.pConnectedTo = pReceivePin; + IPin_AddRef(pReceivePin); + CopyMediaType(&This->pin.mtCurrent, pmt); + + hr = IPin_ReceiveConnection(pReceivePin, &iface->IPin_iface, pmt); + + /* get the IMemInputPin interface we will use to deliver samples to the + * connected pin */ + if (SUCCEEDED(hr)) + { + This->pMemInputPin = NULL; + hr = IPin_QueryInterface(pReceivePin, &IID_IMemInputPin, (LPVOID)&This->pMemInputPin); + + if (SUCCEEDED(hr)) + { + hr = This->pFuncsTable->pfnDecideAllocator(This, This->pMemInputPin, &pMemAlloc); + if (SUCCEEDED(hr)) + This->pAllocator = pMemAlloc; + else if (pMemAlloc) + IMemAllocator_Release(pMemAlloc); + } + + /* break connection if we couldn't get the allocator */ + if (FAILED(hr)) + { + if (This->pMemInputPin) + IMemInputPin_Release(This->pMemInputPin); + This->pMemInputPin = NULL; + + IPin_Disconnect(pReceivePin); + } + } + + if (FAILED(hr)) + { + IPin_Release(This->pin.pConnectedTo); + This->pin.pConnectedTo = NULL; + FreeMediaType(&This->pin.mtCurrent); + } + + TRACE(" -- %x\n", hr); + return hr; +} + +static HRESULT OutputPin_Init(const IPinVtbl *OutputPin_Vtbl, const PIN_INFO * pPinInfo, const BasePinFuncTable* pBaseFuncsTable, const BaseOutputPinFuncTable* pBaseOutputFuncsTable, LPCRITICAL_SECTION pCritSec, BaseOutputPin * pPinImpl) +{ + TRACE("\n"); + + /* Common attributes */ + pPinImpl->pin.IPin_iface.lpVtbl = OutputPin_Vtbl; + pPinImpl->pin.refCount = 1; + pPinImpl->pin.pConnectedTo = NULL; + pPinImpl->pin.pCritSec = pCritSec; + pPinImpl->pin.tStart = 0; + pPinImpl->pin.tStop = 0; + pPinImpl->pin.dRate = 1.0; + Copy_PinInfo(&pPinImpl->pin.pinInfo, pPinInfo); + pPinImpl->pin.pFuncsTable = pBaseFuncsTable; + ZeroMemory(&pPinImpl->pin.mtCurrent, sizeof(AM_MEDIA_TYPE)); + + /* Output pin attributes */ + pPinImpl->pMemInputPin = NULL; + pPinImpl->pAllocator = NULL; + pPinImpl->pFuncsTable = pBaseOutputFuncsTable; + + return S_OK; +} + +HRESULT WINAPI BaseOutputPin_Construct(const IPinVtbl *OutputPin_Vtbl, LONG outputpin_size, const PIN_INFO * pPinInfo, const BasePinFuncTable* pBaseFuncsTable, const BaseOutputPinFuncTable* pBaseOutputFuncsTable, LPCRITICAL_SECTION pCritSec, IPin ** ppPin) +{ + BaseOutputPin * pPinImpl; + + *ppPin = NULL; + + if (pPinInfo->dir != PINDIR_OUTPUT) + { + ERR("Pin direction(%x) != PINDIR_OUTPUT\n", pPinInfo->dir); + return E_INVALIDARG; + } + + assert(outputpin_size >= sizeof(BaseOutputPin)); + assert(pBaseFuncsTable->pfnAttemptConnection); + + pPinImpl = CoTaskMemAlloc(outputpin_size); + + if (!pPinImpl) + return E_OUTOFMEMORY; + + if (SUCCEEDED(OutputPin_Init(OutputPin_Vtbl, pPinInfo, pBaseFuncsTable, pBaseOutputFuncsTable, pCritSec, pPinImpl))) + { + *ppPin = &pPinImpl->pin.IPin_iface; + return S_OK; + } + + CoTaskMemFree(pPinImpl); + return E_FAIL; +} + +/*** Input Pin implementation ***/ + +static inline BaseInputPin *impl_BaseInputPin_from_IPin( IPin *iface ) +{ + return CONTAINING_RECORD(iface, BaseInputPin, pin.IPin_iface); +} + +static inline BaseInputPin *impl_BaseInputPin_from_BasePin( BasePin *iface ) +{ + return CONTAINING_RECORD(iface, BaseInputPin, pin); +} + +HRESULT WINAPI BaseInputPinImpl_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv) +{ + BaseInputPin *This = impl_BaseInputPin_from_IPin(iface); + + TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv); + + *ppv = NULL; + + if (IsEqualIID(riid, &IID_IUnknown)) + *ppv = iface; + else if (IsEqualIID(riid, &IID_IPin)) + *ppv = iface; + else if (IsEqualIID(riid, &IID_IMemInputPin)) + *ppv = &This->IMemInputPin_iface; + else if (IsEqualIID(riid, &IID_IMediaSeeking)) + { + return IBaseFilter_QueryInterface(This->pin.pinInfo.pFilter, &IID_IMediaSeeking, ppv); + } + + if (*ppv) + { + IUnknown_AddRef((IUnknown *)(*ppv)); + return S_OK; + } + + FIXME("No interface for %s!\n", debugstr_guid(riid)); + + return E_NOINTERFACE; +} + +ULONG WINAPI BaseInputPinImpl_Release(IPin * iface) +{ + BaseInputPin *This = impl_BaseInputPin_from_IPin(iface); + ULONG refCount = InterlockedDecrement(&This->pin.refCount); + + TRACE("(%p)->() Release from %d\n", iface, refCount + 1); + + if (!refCount) + { + FreeMediaType(&This->pin.mtCurrent); + if (This->pAllocator) + IMemAllocator_Release(This->pAllocator); + This->pAllocator = NULL; + This->pin.IPin_iface.lpVtbl = NULL; + CoTaskMemFree(This); + return 0; + } + else + return refCount; +} + +HRESULT WINAPI BaseInputPinImpl_Connect(IPin * iface, IPin * pConnector, const AM_MEDIA_TYPE * pmt) +{ + ERR("Outgoing connection on an input pin! (%p, %p)\n", pConnector, pmt); + + return E_UNEXPECTED; +} + + +HRESULT WINAPI BaseInputPinImpl_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) +{ + BaseInputPin *This = impl_BaseInputPin_from_IPin(iface); + PIN_DIRECTION pindirReceive; + HRESULT hr = S_OK; + + TRACE("(%p, %p)\n", pReceivePin, pmt); + dump_AM_MEDIA_TYPE(pmt); + + EnterCriticalSection(This->pin.pCritSec); + { + if (This->pin.pConnectedTo) + hr = VFW_E_ALREADY_CONNECTED; + + if (SUCCEEDED(hr) && This->pin.pFuncsTable->pfnCheckMediaType(&This->pin, pmt) != S_OK) + hr = VFW_E_TYPE_NOT_ACCEPTED; /* FIXME: shouldn't we just map common errors onto + * VFW_E_TYPE_NOT_ACCEPTED and pass the value on otherwise? */ + + 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)) + { + CopyMediaType(&This->pin.mtCurrent, pmt); + This->pin.pConnectedTo = pReceivePin; + IPin_AddRef(pReceivePin); + } + } + LeaveCriticalSection(This->pin.pCritSec); + + return hr; +} + +static HRESULT deliver_endofstream(IPin* pin, LPVOID unused) +{ + return IPin_EndOfStream( pin ); +} + +HRESULT WINAPI BaseInputPinImpl_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt) +{ + BaseInputPin *This = impl_BaseInputPin_from_IPin(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, pmt); + + return (This->pin.pFuncsTable->pfnCheckMediaType(&This->pin, pmt) == S_OK ? S_OK : S_FALSE); +} + +HRESULT WINAPI BaseInputPinImpl_EndOfStream(IPin * iface) +{ + HRESULT hr = S_OK; + BaseInputPin *This = impl_BaseInputPin_from_IPin(iface); + + TRACE("(%p)\n", This); + + EnterCriticalSection(This->pin.pCritSec); + if (This->flushing) + hr = S_FALSE; + else + This->end_of_stream = 1; + LeaveCriticalSection(This->pin.pCritSec); + + if (hr == S_OK) + hr = SendFurther( iface, deliver_endofstream, NULL, NULL ); + return hr; +} + +static HRESULT deliver_beginflush(IPin* pin, LPVOID unused) +{ + return IPin_BeginFlush( pin ); +} + +HRESULT WINAPI BaseInputPinImpl_BeginFlush(IPin * iface) +{ + BaseInputPin *This = impl_BaseInputPin_from_IPin(iface); + HRESULT hr; + TRACE("() semi-stub\n"); + + EnterCriticalSection(This->pin.pCritSec); + This->flushing = 1; + + hr = SendFurther( iface, deliver_beginflush, NULL, NULL ); + LeaveCriticalSection(This->pin.pCritSec); + + return hr; +} + +static HRESULT deliver_endflush(IPin* pin, LPVOID unused) +{ + return IPin_EndFlush( pin ); +} + +HRESULT WINAPI BaseInputPinImpl_EndFlush(IPin * iface) +{ + BaseInputPin *This = impl_BaseInputPin_from_IPin(iface); + HRESULT hr; + TRACE("(%p)\n", This); + + EnterCriticalSection(This->pin.pCritSec); + This->flushing = This->end_of_stream = 0; + + hr = SendFurther( iface, deliver_endflush, NULL, NULL ); + LeaveCriticalSection(This->pin.pCritSec); + + return hr; +} + +typedef struct newsegmentargs +{ + REFERENCE_TIME tStart, tStop; + double rate; +} newsegmentargs; + +static HRESULT deliver_newsegment(IPin *pin, LPVOID data) +{ + newsegmentargs *args = data; + return IPin_NewSegment(pin, args->tStart, args->tStop, args->rate); +} + +HRESULT WINAPI BaseInputPinImpl_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) +{ + BaseInputPin *This = impl_BaseInputPin_from_IPin(iface); + newsegmentargs args; + + TRACE("(%x%08x, %x%08x, %e)\n", (ULONG)(tStart >> 32), (ULONG)tStart, (ULONG)(tStop >> 32), (ULONG)tStop, dRate); + + args.tStart = This->pin.tStart = tStart; + args.tStop = This->pin.tStop = tStop; + args.rate = This->pin.dRate = dRate; + + return SendFurther( iface, deliver_newsegment, &args, NULL ); +} + +static const IPinVtbl InputPin_Vtbl = +{ + BaseInputPinImpl_QueryInterface, + BasePinImpl_AddRef, + BaseInputPinImpl_Release, + BaseInputPinImpl_Connect, + BaseInputPinImpl_ReceiveConnection, + BasePinImpl_Disconnect, + BasePinImpl_ConnectedTo, + BasePinImpl_ConnectionMediaType, + BasePinImpl_QueryPinInfo, + BasePinImpl_QueryDirection, + BasePinImpl_QueryId, + BaseInputPinImpl_QueryAccept, + BasePinImpl_EnumMediaTypes, + BasePinImpl_QueryInternalConnections, + BaseInputPinImpl_EndOfStream, + BaseInputPinImpl_BeginFlush, + BaseInputPinImpl_EndFlush, + BaseInputPinImpl_NewSegment +}; + +/*** IMemInputPin implementation ***/ + +static inline BaseInputPin *impl_from_IMemInputPin( IMemInputPin *iface ) +{ + return CONTAINING_RECORD(iface, BaseInputPin, IMemInputPin_iface); +} + +static HRESULT WINAPI MemInputPin_QueryInterface(IMemInputPin * iface, REFIID riid, LPVOID * ppv) +{ + BaseInputPin *This = impl_from_IMemInputPin(iface); + + return IPin_QueryInterface(&This->pin.IPin_iface, riid, ppv); +} + +static ULONG WINAPI MemInputPin_AddRef(IMemInputPin * iface) +{ + BaseInputPin *This = impl_from_IMemInputPin(iface); + + return IPin_AddRef(&This->pin.IPin_iface); +} + +static ULONG WINAPI MemInputPin_Release(IMemInputPin * iface) +{ + BaseInputPin *This = impl_from_IMemInputPin(iface); + + return IPin_Release(&This->pin.IPin_iface); +} + +static HRESULT WINAPI MemInputPin_GetAllocator(IMemInputPin * iface, IMemAllocator ** ppAllocator) +{ + BaseInputPin *This = impl_from_IMemInputPin(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, ppAllocator); + + *ppAllocator = This->pAllocator; + if (*ppAllocator) + IMemAllocator_AddRef(*ppAllocator); + + return *ppAllocator ? S_OK : VFW_E_NO_ALLOCATOR; +} + +static HRESULT WINAPI MemInputPin_NotifyAllocator(IMemInputPin * iface, IMemAllocator * pAllocator, BOOL bReadOnly) +{ + BaseInputPin *This = impl_from_IMemInputPin(iface); + + TRACE("(%p/%p)->(%p, %d)\n", This, iface, pAllocator, bReadOnly); + + if (bReadOnly) + FIXME("Read only flag not handled yet!\n"); + + /* FIXME: Should we release the allocator on disconnection? */ + if (!pAllocator) + { + WARN("Null allocator\n"); + return E_POINTER; + } + + if (This->preferred_allocator && pAllocator != This->preferred_allocator) + return E_FAIL; + + if (This->pAllocator) + IMemAllocator_Release(This->pAllocator); + This->pAllocator = pAllocator; + if (This->pAllocator) + IMemAllocator_AddRef(This->pAllocator); + + return S_OK; +} + +static HRESULT WINAPI MemInputPin_GetAllocatorRequirements(IMemInputPin * iface, ALLOCATOR_PROPERTIES * pProps) +{ + BaseInputPin *This = impl_from_IMemInputPin(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, pProps); + + /* override this method if you have any specific requirements */ + + return E_NOTIMPL; +} + +static HRESULT WINAPI MemInputPin_Receive(IMemInputPin * iface, IMediaSample * pSample) +{ + BaseInputPin *This = impl_from_IMemInputPin(iface); + HRESULT hr = S_FALSE; + + /* this trace commented out for performance reasons */ + /*TRACE("(%p/%p)->(%p)\n", This, iface, pSample);*/ + if (This->pFuncsTable->pfnReceive) + hr = This->pFuncsTable->pfnReceive(This, pSample); + return hr; +} + +static HRESULT WINAPI MemInputPin_ReceiveMultiple(IMemInputPin * iface, IMediaSample ** pSamples, LONG nSamples, LONG *nSamplesProcessed) +{ + HRESULT hr = S_OK; + BaseInputPin *This = impl_from_IMemInputPin(iface); + + TRACE("(%p/%p)->(%p, %d, %p)\n", This, iface, pSamples, nSamples, nSamplesProcessed); + + for (*nSamplesProcessed = 0; *nSamplesProcessed < nSamples; (*nSamplesProcessed)++) + { + hr = IMemInputPin_Receive(iface, pSamples[*nSamplesProcessed]); + if (hr != S_OK) + break; + } + + return hr; +} + +static HRESULT WINAPI MemInputPin_ReceiveCanBlock(IMemInputPin * iface) +{ + BaseInputPin *This = impl_from_IMemInputPin(iface); + + TRACE("(%p/%p)->()\n", This, iface); + + return S_OK; +} + +static const IMemInputPinVtbl MemInputPin_Vtbl = +{ + MemInputPin_QueryInterface, + MemInputPin_AddRef, + MemInputPin_Release, + MemInputPin_GetAllocator, + MemInputPin_NotifyAllocator, + MemInputPin_GetAllocatorRequirements, + MemInputPin_Receive, + MemInputPin_ReceiveMultiple, + MemInputPin_ReceiveCanBlock +}; + +static HRESULT InputPin_Init(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo, + const BasePinFuncTable* pBaseFuncsTable, const BaseInputPinFuncTable* pBaseInputFuncsTable, + LPCRITICAL_SECTION pCritSec, IMemAllocator *allocator, BaseInputPin * pPinImpl) +{ + TRACE("\n"); + + /* Common attributes */ + pPinImpl->pin.refCount = 1; + pPinImpl->pin.pConnectedTo = NULL; + pPinImpl->pin.pCritSec = pCritSec; + pPinImpl->pin.tStart = 0; + pPinImpl->pin.tStop = 0; + pPinImpl->pin.dRate = 1.0; + Copy_PinInfo(&pPinImpl->pin.pinInfo, pPinInfo); + ZeroMemory(&pPinImpl->pin.mtCurrent, sizeof(AM_MEDIA_TYPE)); + pPinImpl->pin.pFuncsTable = pBaseFuncsTable; + + /* Input pin attributes */ + pPinImpl->pFuncsTable = pBaseInputFuncsTable; + pPinImpl->pAllocator = pPinImpl->preferred_allocator = allocator; + if (pPinImpl->preferred_allocator) + IMemAllocator_AddRef(pPinImpl->preferred_allocator); + pPinImpl->pin.IPin_iface.lpVtbl = InputPin_Vtbl; + pPinImpl->IMemInputPin_iface.lpVtbl = &MemInputPin_Vtbl; + pPinImpl->flushing = pPinImpl->end_of_stream = 0; + + return S_OK; +} + +HRESULT BaseInputPin_Construct(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo, + const BasePinFuncTable* pBaseFuncsTable, const BaseInputPinFuncTable* pBaseInputFuncsTable, + LPCRITICAL_SECTION pCritSec, IMemAllocator *allocator, IPin ** ppPin) +{ + BaseInputPin * pPinImpl; + + *ppPin = NULL; + + assert(pBaseFuncsTable->pfnCheckMediaType); + + if (pPinInfo->dir != PINDIR_INPUT) + { + ERR("Pin direction(%x) != PINDIR_INPUT\n", pPinInfo->dir); + return E_INVALIDARG; + } + + pPinImpl = CoTaskMemAlloc(sizeof(*pPinImpl)); + + if (!pPinImpl) + return E_OUTOFMEMORY; + + if (SUCCEEDED(InputPin_Init(InputPin_Vtbl, pPinInfo, pBaseFuncsTable, pBaseInputFuncsTable, pCritSec, allocator, pPinImpl))) + { + *ppPin = (IPin *)pPinImpl; + return S_OK; + } + + CoTaskMemFree(pPinImpl); + return E_FAIL; +} diff --git a/reactos/lib/3rdparty/strmbase/pospass.c b/reactos/lib/3rdparty/strmbase/pospass.c new file mode 100644 index 00000000000..71c1dc67d17 --- /dev/null +++ b/reactos/lib/3rdparty/strmbase/pospass.c @@ -0,0 +1,938 @@ +/* + * Filter Seeking and Control Interfaces + * + * Copyright 2003 Robert Shearman + * Copyright 2012 Aric Stewart, CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +/* FIXME: critical sections */ + +#define COBJMACROS + +#include "dshow.h" +#include "uuids.h" + +#include "wine/debug.h" +#include "wine/strmbase.h" + +#include + +WINE_DEFAULT_DEBUG_CHANNEL(strmbase); + +static const IMediaSeekingVtbl IMediaSeekingPassThru_Vtbl; +static const IMediaPositionVtbl IMediaPositionPassThru_Vtbl; + +typedef struct PassThruImpl { + IUnknown IUnknown_inner; + ISeekingPassThru ISeekingPassThru_iface; + IMediaSeeking IMediaSeeking_iface; + IMediaPosition IMediaPosition_iface; + BaseDispatch baseDispatch; + + LONG ref; + IUnknown * outer_unk; + IPin * pin; + BOOL bUnkOuterValid; + BOOL bAggregatable; + BOOL renderer; + CRITICAL_SECTION time_cs; + BOOL timevalid; + REFERENCE_TIME time_earliest; +} PassThruImpl; + +static inline PassThruImpl *impl_from_IUnknown_inner(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, PassThruImpl, IUnknown_inner); +} + +static inline PassThruImpl *impl_from_ISeekingPassThru(ISeekingPassThru *iface) +{ + return CONTAINING_RECORD(iface, PassThruImpl, ISeekingPassThru_iface); +} + +static inline PassThruImpl *impl_from_IMediaSeeking(IMediaSeeking *iface) +{ + return CONTAINING_RECORD(iface, PassThruImpl, IMediaSeeking_iface); +} + +static inline PassThruImpl *impl_from_IMediaPosition(IMediaPosition *iface) +{ + return CONTAINING_RECORD(iface, PassThruImpl, IMediaPosition_iface); +} + +static HRESULT WINAPI SeekInner_QueryInterface(IUnknown * iface, + REFIID riid, + LPVOID *ppvObj) { + PassThruImpl *This = impl_from_IUnknown_inner(iface); + TRACE("(%p)->(%s (%p), %p)\n", This, debugstr_guid(riid), riid, ppvObj); + + if (This->bAggregatable) + This->bUnkOuterValid = TRUE; + + if (IsEqualGUID(&IID_IUnknown, riid)) + { + *ppvObj = &(This->IUnknown_inner); + TRACE(" returning IUnknown interface (%p)\n", *ppvObj); + } else if (IsEqualGUID(&IID_ISeekingPassThru, riid)) { + *ppvObj = &(This->ISeekingPassThru_iface); + TRACE(" returning ISeekingPassThru interface (%p)\n", *ppvObj); + } else if (IsEqualGUID(&IID_IMediaSeeking, riid)) { + *ppvObj = &(This->IMediaSeeking_iface); + TRACE(" returning IMediaSeeking interface (%p)\n", *ppvObj); + } else if (IsEqualGUID(&IID_IMediaPosition, riid)) { + *ppvObj = &(This->IMediaPosition_iface); + TRACE(" returning IMediaPosition interface (%p)\n", *ppvObj); + } else { + *ppvObj = NULL; + FIXME("unknown interface %s\n", debugstr_guid(riid)); + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown *)(*ppvObj)); + return S_OK; +} + +static ULONG WINAPI SeekInner_AddRef(IUnknown * iface) { + PassThruImpl *This = impl_from_IUnknown_inner(iface); + ULONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p)->(): new ref = %d\n", This, ref); + + return ref; +} + +static ULONG WINAPI SeekInner_Release(IUnknown * iface) { + PassThruImpl *This = impl_from_IUnknown_inner(iface); + ULONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p)->(): new ref = %d\n", This, ref); + + if (ref == 0) + { + BaseDispatch_Destroy(&This->baseDispatch); + This->time_cs.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&This->time_cs); + CoTaskMemFree(This); + } + return ref; +} + +static const IUnknownVtbl IInner_VTable = +{ + SeekInner_QueryInterface, + SeekInner_AddRef, + SeekInner_Release +}; + +/* Generic functions for aggregation */ +static HRESULT SeekOuter_QueryInterface(PassThruImpl *This, REFIID riid, LPVOID *ppv) +{ + if (This->bAggregatable) + This->bUnkOuterValid = TRUE; + + if (This->outer_unk) + { + if (This->bAggregatable) + return IUnknown_QueryInterface(This->outer_unk, riid, ppv); + + if (IsEqualIID(riid, &IID_IUnknown)) + { + HRESULT hr; + + IUnknown_AddRef((IUnknown *)&(This->IUnknown_inner)); + hr = IUnknown_QueryInterface((IUnknown *)&(This->IUnknown_inner), riid, ppv); + IUnknown_Release((IUnknown *)&(This->IUnknown_inner)); + This->bAggregatable = TRUE; + return hr; + } + + *ppv = NULL; + return E_NOINTERFACE; + } + + return IUnknown_QueryInterface((IUnknown *)&(This->IUnknown_inner), riid, ppv); +} + +static ULONG SeekOuter_AddRef(PassThruImpl *This) +{ + if (This->outer_unk && This->bUnkOuterValid) + return IUnknown_AddRef(This->outer_unk); + return IUnknown_AddRef((IUnknown *)&(This->IUnknown_inner)); +} + +static ULONG SeekOuter_Release(PassThruImpl *This) +{ + if (This->outer_unk && This->bUnkOuterValid) + return IUnknown_Release(This->outer_unk); + return IUnknown_Release((IUnknown *)&(This->IUnknown_inner)); +} + +static HRESULT WINAPI SeekingPassThru_QueryInterface(ISeekingPassThru *iface, REFIID riid, LPVOID *ppvObj) +{ + PassThruImpl *This = impl_from_ISeekingPassThru(iface); + + TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); + + return SeekOuter_QueryInterface(This, riid, ppvObj); +} + +static ULONG WINAPI SeekingPassThru_AddRef(ISeekingPassThru *iface) +{ + PassThruImpl *This = impl_from_ISeekingPassThru(iface); + + TRACE("(%p/%p)->()\n", This, iface); + + return SeekOuter_AddRef(This); +} + +static ULONG WINAPI SeekingPassThru_Release(ISeekingPassThru *iface) +{ + PassThruImpl *This = impl_from_ISeekingPassThru(iface); + + TRACE("(%p/%p)->()\n", This, iface); + + return SeekOuter_Release(This); +} + +static HRESULT WINAPI SeekingPassThru_Init(ISeekingPassThru *iface, BOOL renderer, IPin *pin) +{ + PassThruImpl *This = impl_from_ISeekingPassThru(iface); + + TRACE("(%p/%p)->(%d, %p)\n", This, iface, renderer, pin); + + if (This->pin) + FIXME("Re-initializing?\n"); + + This->renderer = renderer; + This->pin = pin; + + return S_OK; +} + +static const ISeekingPassThruVtbl ISeekingPassThru_Vtbl = +{ + SeekingPassThru_QueryInterface, + SeekingPassThru_AddRef, + SeekingPassThru_Release, + SeekingPassThru_Init +}; + +HRESULT WINAPI CreatePosPassThru(IUnknown* pUnkOuter, BOOL bRenderer, IPin *pPin, IUnknown **ppPassThru) +{ + HRESULT hr; + ISeekingPassThru *passthru; + + hr = CoCreateInstance(&CLSID_SeekingPassThru, pUnkOuter, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)ppPassThru); + + IUnknown_QueryInterface(*ppPassThru, &IID_ISeekingPassThru, (void**)&passthru); + hr = ISeekingPassThru_Init(passthru, bRenderer, pPin); + ISeekingPassThru_Release(passthru); + + return hr; +} + +HRESULT WINAPI PosPassThru_Construct(IUnknown *pUnkOuter, LPVOID *ppPassThru) +{ + PassThruImpl *fimpl; + + TRACE("(%p,%p)\n", pUnkOuter, ppPassThru); + + *ppPassThru = fimpl = CoTaskMemAlloc(sizeof(*fimpl)); + if (!fimpl) + return E_OUTOFMEMORY; + + fimpl->outer_unk = pUnkOuter; + fimpl->bUnkOuterValid = FALSE; + fimpl->bAggregatable = FALSE; + fimpl->IUnknown_inner.lpVtbl = &IInner_VTable; + fimpl->ISeekingPassThru_iface.lpVtbl = &ISeekingPassThru_Vtbl; + fimpl->IMediaSeeking_iface.lpVtbl = &IMediaSeekingPassThru_Vtbl; + fimpl->IMediaPosition_iface.lpVtbl = &IMediaPositionPassThru_Vtbl; + fimpl->ref = 1; + fimpl->pin = NULL; + fimpl->timevalid = 0; + InitializeCriticalSection(&fimpl->time_cs); + fimpl->time_cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": PassThruImpl.time_cs"); + BaseDispatch_Init(&fimpl->baseDispatch, &IID_IMediaPosition); + return S_OK; +} + +static HRESULT WINAPI MediaSeekingPassThru_QueryInterface(IMediaSeeking *iface, REFIID riid, LPVOID *ppvObj) +{ + PassThruImpl *This = impl_from_IMediaSeeking(iface); + + TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); + + return SeekOuter_QueryInterface(This, riid, ppvObj); +} + +static ULONG WINAPI MediaSeekingPassThru_AddRef(IMediaSeeking *iface) +{ + PassThruImpl *This = impl_from_IMediaSeeking(iface); + + TRACE("(%p/%p)->()\n", iface, This); + + return SeekOuter_AddRef(This); +} + +static ULONG WINAPI MediaSeekingPassThru_Release(IMediaSeeking *iface) +{ + PassThruImpl *This = impl_from_IMediaSeeking(iface); + + TRACE("(%p/%p)->()\n", iface, This); + + return SeekOuter_Release(This); +} + +static HRESULT get_connected(PassThruImpl *This, REFIID riid, LPVOID *ppvObj) { + HRESULT hr; + IPin *pin; + *ppvObj = NULL; + hr = IPin_ConnectedTo(This->pin, &pin); + if (FAILED(hr)) + return VFW_E_NOT_CONNECTED; + hr = IPin_QueryInterface(pin, riid, ppvObj); + IPin_Release(pin); + if (FAILED(hr)) + hr = E_NOTIMPL; + return hr; +} + +static HRESULT WINAPI MediaSeekingPassThru_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities) +{ + PassThruImpl *This = impl_from_IMediaSeeking(iface); + IMediaSeeking *seek; + HRESULT hr; + TRACE("(%p/%p)->(%p)\n", iface, This, pCapabilities); + hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); + if (SUCCEEDED(hr)) { + hr = IMediaSeeking_GetCapabilities(seek, pCapabilities); + IMediaSeeking_Release(seek); + } + else + return E_NOTIMPL; + return hr; +} + +static HRESULT WINAPI MediaSeekingPassThru_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities) +{ + PassThruImpl *This = impl_from_IMediaSeeking(iface); + IMediaSeeking *seek; + HRESULT hr; + TRACE("(%p/%p)->(%p)\n", iface, This, pCapabilities); + hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); + if (SUCCEEDED(hr)) { + hr = IMediaSeeking_CheckCapabilities(seek, pCapabilities); + IMediaSeeking_Release(seek); + } + else + return E_NOTIMPL; + return hr; +} + +static HRESULT WINAPI MediaSeekingPassThru_IsFormatSupported(IMediaSeeking * iface, const GUID * pFormat) +{ + PassThruImpl *This = impl_from_IMediaSeeking(iface); + IMediaSeeking *seek; + HRESULT hr; + TRACE("(%p/%p)->(%s)\n", iface, This, debugstr_guid(pFormat)); + hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); + if (SUCCEEDED(hr)) { + hr = IMediaSeeking_IsFormatSupported(seek, pFormat); + IMediaSeeking_Release(seek); + } + else + return E_NOTIMPL; + return hr; +} + +static HRESULT WINAPI MediaSeekingPassThru_QueryPreferredFormat(IMediaSeeking * iface, GUID * pFormat) +{ + PassThruImpl *This = impl_from_IMediaSeeking(iface); + IMediaSeeking *seek; + HRESULT hr; + TRACE("(%p/%p)->(%p)\n", iface, This, pFormat); + hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); + if (SUCCEEDED(hr)) { + hr = IMediaSeeking_QueryPreferredFormat(seek, pFormat); + IMediaSeeking_Release(seek); + } + else + return E_NOTIMPL; + return hr; +} + +static HRESULT WINAPI MediaSeekingPassThru_GetTimeFormat(IMediaSeeking * iface, GUID * pFormat) +{ + PassThruImpl *This = impl_from_IMediaSeeking(iface); + IMediaSeeking *seek; + HRESULT hr; + TRACE("(%p/%p)->(%p)\n", iface, This, pFormat); + hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); + if (SUCCEEDED(hr)) { + hr = IMediaSeeking_GetTimeFormat(seek, pFormat); + IMediaSeeking_Release(seek); + } + else + return E_NOTIMPL; + return hr; +} + +static HRESULT WINAPI MediaSeekingPassThru_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat) +{ + PassThruImpl *This = impl_from_IMediaSeeking(iface); + IMediaSeeking *seek; + HRESULT hr; + TRACE("(%p/%p)->(%s)\n", iface, This, debugstr_guid(pFormat)); + hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); + if (SUCCEEDED(hr)) { + hr = IMediaSeeking_IsUsingTimeFormat(seek, pFormat); + IMediaSeeking_Release(seek); + } + else + return E_NOTIMPL; + return hr; +} + +static HRESULT WINAPI MediaSeekingPassThru_SetTimeFormat(IMediaSeeking * iface, const GUID * pFormat) +{ + PassThruImpl *This = impl_from_IMediaSeeking(iface); + IMediaSeeking *seek; + HRESULT hr; + TRACE("(%p/%p)->(%s)\n", iface, This, debugstr_guid(pFormat)); + hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); + if (SUCCEEDED(hr)) { + hr = IMediaSeeking_SetTimeFormat(seek, pFormat); + IMediaSeeking_Release(seek); + } + else + return E_NOTIMPL; + return hr; +} + +static HRESULT WINAPI MediaSeekingPassThru_GetDuration(IMediaSeeking * iface, LONGLONG * pDuration) +{ + PassThruImpl *This = impl_from_IMediaSeeking(iface); + IMediaSeeking *seek; + HRESULT hr; + TRACE("(%p/%p)->(%p)\n", iface, This, pDuration); + hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); + if (SUCCEEDED(hr)) { + hr = IMediaSeeking_GetDuration(seek, pDuration); + IMediaSeeking_Release(seek); + } + else + return E_NOTIMPL; + return hr; +} + +static HRESULT WINAPI MediaSeekingPassThru_GetStopPosition(IMediaSeeking * iface, LONGLONG * pStop) +{ + PassThruImpl *This = impl_from_IMediaSeeking(iface); + IMediaSeeking *seek; + HRESULT hr; + TRACE("(%p/%p)->(%p)\n", iface, This, pStop); + hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); + if (SUCCEEDED(hr)) { + hr = IMediaSeeking_GetStopPosition(seek, pStop); + IMediaSeeking_Release(seek); + } + else + return E_NOTIMPL; + return hr; +} + +static HRESULT WINAPI MediaSeekingPassThru_GetCurrentPosition(IMediaSeeking * iface, LONGLONG * pCurrent) +{ + PassThruImpl *This = impl_from_IMediaSeeking(iface); + IMediaSeeking *seek; + HRESULT hr = S_OK; + TRACE("(%p/%p)->(%p)\n", iface, This, pCurrent); + if (!pCurrent) + return E_POINTER; + EnterCriticalSection(&This->time_cs); + if (This->timevalid) + *pCurrent = This->time_earliest; + else + hr = E_FAIL; + LeaveCriticalSection(&This->time_cs); + if (SUCCEEDED(hr)) { + hr = IMediaSeeking_ConvertTimeFormat(iface, pCurrent, NULL, *pCurrent, &TIME_FORMAT_MEDIA_TIME); + return hr; + } + hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); + if (SUCCEEDED(hr)) { + hr = IMediaSeeking_GetCurrentPosition(seek, pCurrent); + IMediaSeeking_Release(seek); + } + else + return E_NOTIMPL; + return hr; +} + +static HRESULT WINAPI MediaSeekingPassThru_ConvertTimeFormat(IMediaSeeking * iface, LONGLONG * pTarget, const GUID * pTargetFormat, LONGLONG Source, const GUID * pSourceFormat) +{ + PassThruImpl *This = impl_from_IMediaSeeking(iface); + IMediaSeeking *seek; + HRESULT hr; + TRACE("(%p/%p)->(%p,%s,%x%08x,%s)\n", iface, This, pTarget, debugstr_guid(pTargetFormat), (DWORD)(Source>>32), (DWORD)Source, debugstr_guid(pSourceFormat)); + hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); + if (SUCCEEDED(hr)) { + hr = IMediaSeeking_ConvertTimeFormat(seek, pTarget, pTargetFormat, Source, pSourceFormat); + IMediaSeeking_Release(seek); + } + else + return E_NOTIMPL; + return hr; +} + +static HRESULT WINAPI MediaSeekingPassThru_SetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, DWORD dwCurrentFlags, LONGLONG * pStop, DWORD dwStopFlags) +{ + PassThruImpl *This = impl_from_IMediaSeeking(iface); + IMediaSeeking *seek; + HRESULT hr; + TRACE("(%p/%p)->(%p,%x,%p,%x)\n", iface, This, pCurrent, dwCurrentFlags, pStop, dwStopFlags); + hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); + if (SUCCEEDED(hr)) { + hr = IMediaSeeking_SetPositions(seek, pCurrent, dwCurrentFlags, pStop, dwStopFlags); + IMediaSeeking_Release(seek); + } else if (hr == VFW_E_NOT_CONNECTED) + hr = S_OK; + return hr; +} + +static HRESULT WINAPI MediaSeekingPassThru_GetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, LONGLONG * pStop) +{ + PassThruImpl *This = impl_from_IMediaSeeking(iface); + IMediaSeeking *seek; + HRESULT hr; + TRACE("(%p/%p)->(%p, %p)\n", iface, This, pCurrent, pStop); + hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); + if (SUCCEEDED(hr)) { + hr = IMediaSeeking_GetPositions(seek, pCurrent, pStop); + IMediaSeeking_Release(seek); + } + else + return E_NOTIMPL; + return hr; +} + +static HRESULT WINAPI MediaSeekingPassThru_GetAvailable(IMediaSeeking * iface, LONGLONG * pEarliest, LONGLONG * pLatest) +{ + PassThruImpl *This = impl_from_IMediaSeeking(iface); + IMediaSeeking *seek; + HRESULT hr; + TRACE("(%p/%p)->(%p,%p)\n", iface, This, pEarliest, pLatest); + hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); + if (SUCCEEDED(hr)) { + hr = IMediaSeeking_GetAvailable(seek, pEarliest, pLatest); + IMediaSeeking_Release(seek); + } + else + return E_NOTIMPL; + return hr; +} + +static HRESULT WINAPI MediaSeekingPassThru_SetRate(IMediaSeeking * iface, double dRate) +{ + PassThruImpl *This = impl_from_IMediaSeeking(iface); + IMediaSeeking *seek; + HRESULT hr; + TRACE("(%p/%p)->(%e)\n", iface, This, dRate); + hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); + if (SUCCEEDED(hr)) { + hr = IMediaSeeking_SetRate(seek, dRate); + IMediaSeeking_Release(seek); + } + else + return E_NOTIMPL; + return hr; +} + +static HRESULT WINAPI MediaSeekingPassThru_GetRate(IMediaSeeking * iface, double * dRate) +{ + PassThruImpl *This = impl_from_IMediaSeeking(iface); + IMediaSeeking *seek; + HRESULT hr; + TRACE("(%p/%p)->(%p)\n", iface, This, dRate); + hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); + if (SUCCEEDED(hr)) { + hr = IMediaSeeking_GetRate(seek, dRate); + IMediaSeeking_Release(seek); + } + else + return E_NOTIMPL; + return hr; +} + +static HRESULT WINAPI MediaSeekingPassThru_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll) +{ + PassThruImpl *This = impl_from_IMediaSeeking(iface); + IMediaSeeking *seek; + HRESULT hr; + TRACE("(%p)\n", pPreroll); + hr = get_connected(This, &IID_IMediaSeeking, (LPVOID*)&seek); + if (SUCCEEDED(hr)) { + hr = IMediaSeeking_GetPreroll(seek, pPreroll); + IMediaSeeking_Release(seek); + } + else + return E_NOTIMPL; + return hr; +} + +HRESULT WINAPI RendererPosPassThru_RegisterMediaTime(IUnknown *iface, REFERENCE_TIME start) +{ + PassThruImpl *This = impl_from_IUnknown_inner(iface); + EnterCriticalSection(&This->time_cs); + This->time_earliest = start; + This->timevalid = 1; + LeaveCriticalSection(&This->time_cs); + return S_OK; +} + +HRESULT WINAPI RendererPosPassThru_ResetMediaTime(IUnknown *iface) +{ + PassThruImpl *This = impl_from_IUnknown_inner(iface); + EnterCriticalSection(&This->time_cs); + This->timevalid = 0; + LeaveCriticalSection(&This->time_cs); + return S_OK; +} + +HRESULT WINAPI RendererPosPassThru_EOS(IUnknown *iface) +{ + PassThruImpl *This = impl_from_IUnknown_inner(iface); + REFERENCE_TIME time; + HRESULT hr; + hr = IMediaSeeking_GetStopPosition(&This->IMediaSeeking_iface, &time); + EnterCriticalSection(&This->time_cs); + if (SUCCEEDED(hr)) { + This->timevalid = 1; + This->time_earliest = time; + } else + This->timevalid = 0; + LeaveCriticalSection(&This->time_cs); + return hr; +} + +static const IMediaSeekingVtbl IMediaSeekingPassThru_Vtbl = +{ + MediaSeekingPassThru_QueryInterface, + MediaSeekingPassThru_AddRef, + MediaSeekingPassThru_Release, + MediaSeekingPassThru_GetCapabilities, + MediaSeekingPassThru_CheckCapabilities, + MediaSeekingPassThru_IsFormatSupported, + MediaSeekingPassThru_QueryPreferredFormat, + MediaSeekingPassThru_GetTimeFormat, + MediaSeekingPassThru_IsUsingTimeFormat, + MediaSeekingPassThru_SetTimeFormat, + MediaSeekingPassThru_GetDuration, + MediaSeekingPassThru_GetStopPosition, + MediaSeekingPassThru_GetCurrentPosition, + MediaSeekingPassThru_ConvertTimeFormat, + MediaSeekingPassThru_SetPositions, + MediaSeekingPassThru_GetPositions, + MediaSeekingPassThru_GetAvailable, + MediaSeekingPassThru_SetRate, + MediaSeekingPassThru_GetRate, + MediaSeekingPassThru_GetPreroll +}; + +static HRESULT WINAPI MediaPositionPassThru_QueryInterface(IMediaPosition *iface, REFIID riid, LPVOID *ppvObj) +{ + PassThruImpl *This = impl_from_IMediaPosition(iface); + + TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj); + + return SeekOuter_QueryInterface(This, riid, ppvObj); +} + +static ULONG WINAPI MediaPositionPassThru_AddRef(IMediaPosition *iface) +{ + PassThruImpl *This = impl_from_IMediaPosition(iface); + + TRACE("(%p/%p)->()\n", iface, This); + + return SeekOuter_AddRef(This); +} + +static ULONG WINAPI MediaPositionPassThru_Release(IMediaPosition *iface) +{ + PassThruImpl *This = impl_from_IMediaPosition(iface); + + TRACE("(%p/%p)->()\n", iface, This); + + return SeekOuter_Release(This); +} + +static HRESULT WINAPI MediaPositionPassThru_GetTypeInfoCount(IMediaPosition *iface, UINT*pctinfo) +{ + PassThruImpl *This = impl_from_IMediaPosition(iface); + + return BaseDispatchImpl_GetTypeInfoCount(&This->baseDispatch, pctinfo); +} + +static HRESULT WINAPI MediaPositionPassThru_GetTypeInfo(IMediaPosition *iface, UINT iTInfo, LCID lcid, ITypeInfo**ppTInfo) +{ + PassThruImpl *This = impl_from_IMediaPosition(iface); + + return BaseDispatchImpl_GetTypeInfo(&This->baseDispatch, &IID_NULL, iTInfo, lcid, ppTInfo); +} + +static HRESULT WINAPI MediaPositionPassThru_GetIDsOfNames(IMediaPosition *iface, REFIID riid, LPOLESTR*rgszNames, UINT cNames, LCID lcid, DISPID*rgDispId) +{ + PassThruImpl *This = impl_from_IMediaPosition(iface); + + return BaseDispatchImpl_GetIDsOfNames(&This->baseDispatch, riid, rgszNames, cNames, lcid, rgDispId); +} + +static HRESULT WINAPI MediaPositionPassThru_Invoke(IMediaPosition *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS*pDispParams, VARIANT*pVarResult, EXCEPINFO*pExepInfo, UINT*puArgErr) +{ + PassThruImpl *This = impl_from_IMediaPosition(iface); + HRESULT hr = S_OK; + ITypeInfo *pTypeInfo; + + hr = BaseDispatchImpl_GetTypeInfo(&This->baseDispatch, riid, 1, lcid, &pTypeInfo); + if (SUCCEEDED(hr)) + { + hr = ITypeInfo_Invoke(pTypeInfo, &This->IMediaPosition_iface, dispIdMember, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr); + ITypeInfo_Release(pTypeInfo); + } + + return hr; +} + +static HRESULT WINAPI MediaPositionPassThru_get_Duration(IMediaPosition *iface, REFTIME *plength) +{ + PassThruImpl *This = impl_from_IMediaPosition(iface); + IMediaPosition *pos; + HRESULT hr; + + TRACE("(%p)\n", plength); + + hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos); + if (SUCCEEDED(hr)) { + hr = IMediaPosition_get_Duration(pos, plength); + IMediaPosition_Release(pos); + } + else + return E_NOTIMPL; + return hr; +} + +static HRESULT WINAPI MediaPositionPassThru_put_CurrentPosition(IMediaPosition *iface, REFTIME llTime) +{ + PassThruImpl *This = impl_from_IMediaPosition(iface); + IMediaPosition *pos; + HRESULT hr; + + TRACE("(%s)\n", wine_dbgstr_longlong(llTime)); + + hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos); + if (SUCCEEDED(hr)) { + hr = IMediaPosition_put_CurrentPosition(pos, llTime); + IMediaPosition_Release(pos); + } + else + return E_NOTIMPL; + return hr; +} + +static HRESULT WINAPI MediaPositionPassThru_get_CurrentPosition(IMediaPosition *iface, REFTIME *pllTime) +{ + PassThruImpl *This = impl_from_IMediaPosition(iface); + IMediaPosition *pos; + HRESULT hr; + + TRACE("(%p)\n", pllTime); + + hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos); + if (SUCCEEDED(hr)) { + hr = IMediaPosition_get_CurrentPosition(pos, pllTime); + IMediaPosition_Release(pos); + } + else + return E_NOTIMPL; + return hr; +} + +static HRESULT WINAPI MediaPositionPassThru_get_StopTime(IMediaPosition *iface, REFTIME *pllTime) +{ + PassThruImpl *This = impl_from_IMediaPosition(iface); + IMediaPosition *pos; + HRESULT hr; + + TRACE("(%p)\n", pllTime); + + hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos); + if (SUCCEEDED(hr)) { + hr = IMediaPosition_get_StopTime(pos, pllTime); + IMediaPosition_Release(pos); + } + else + return E_NOTIMPL; + return hr; +} + +static HRESULT WINAPI MediaPositionPassThru_put_StopTime(IMediaPosition *iface, REFTIME llTime) +{ + PassThruImpl *This = impl_from_IMediaPosition(iface); + IMediaPosition *pos; + HRESULT hr; + + TRACE("(%s)\n", wine_dbgstr_longlong(llTime)); + + hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos); + if (SUCCEEDED(hr)) { + hr = IMediaPosition_put_StopTime(pos, llTime); + IMediaPosition_Release(pos); + } + else + return E_NOTIMPL; + return hr; +} + +static HRESULT WINAPI MediaPositionPassThru_get_PrerollTime(IMediaPosition *iface, REFTIME *pllTime) +{ + PassThruImpl *This = impl_from_IMediaPosition(iface); + IMediaPosition *pos; + HRESULT hr; + + TRACE("(%p)\n", pllTime); + + hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos); + if (SUCCEEDED(hr)) { + hr = IMediaPosition_get_PrerollTime(pos, pllTime); + IMediaPosition_Release(pos); + } + else + return E_NOTIMPL; + return hr; +} + +static HRESULT WINAPI MediaPositionPassThru_put_PrerollTime(IMediaPosition *iface, REFTIME llTime) +{ + PassThruImpl *This = impl_from_IMediaPosition(iface); + IMediaPosition *pos; + HRESULT hr; + + TRACE("(%s)\n", wine_dbgstr_longlong(llTime)); + + hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos); + if (SUCCEEDED(hr)) { + hr = IMediaPosition_put_PrerollTime(pos, llTime); + IMediaPosition_Release(pos); + } + else + return E_NOTIMPL; + return hr; +} + +static HRESULT WINAPI MediaPositionPassThru_put_Rate(IMediaPosition *iface, double dRate) +{ + PassThruImpl *This = impl_from_IMediaPosition(iface); + IMediaPosition *pos; + HRESULT hr; + + TRACE("(%f)\n", dRate); + + hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos); + if (SUCCEEDED(hr)) { + hr = IMediaPosition_put_Rate(pos, dRate); + IMediaPosition_Release(pos); + } + else + return E_NOTIMPL; + return hr; +} + +static HRESULT WINAPI MediaPositionPassThru_get_Rate(IMediaPosition *iface, double *pdRate) +{ + PassThruImpl *This = impl_from_IMediaPosition(iface); + IMediaPosition *pos; + HRESULT hr; + + TRACE("(%p)\n", pdRate); + + hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos); + if (SUCCEEDED(hr)) { + hr = IMediaPosition_get_Rate(pos, pdRate); + IMediaPosition_Release(pos); + } + else + return E_NOTIMPL; + return hr; +} + +static HRESULT WINAPI MediaPositionPassThru_CanSeekForward(IMediaPosition *iface, LONG *pCanSeekForward) +{ + PassThruImpl *This = impl_from_IMediaPosition(iface); + IMediaPosition *pos; + HRESULT hr; + + TRACE("(%p)\n", pCanSeekForward); + + hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos); + if (SUCCEEDED(hr)) { + hr = IMediaPosition_CanSeekForward(pos, pCanSeekForward); + IMediaPosition_Release(pos); + } + else + return E_NOTIMPL; + return hr; +} + +static HRESULT WINAPI MediaPositionPassThru_CanSeekBackward(IMediaPosition *iface, LONG *pCanSeekBackward) +{ + PassThruImpl *This = impl_from_IMediaPosition(iface); + IMediaPosition *pos; + HRESULT hr; + + TRACE("(%p)\n", pCanSeekBackward); + + hr = get_connected(This, &IID_IMediaPosition, (LPVOID*)&pos); + if (SUCCEEDED(hr)) { + hr = IMediaPosition_CanSeekBackward(pos, pCanSeekBackward); + IMediaPosition_Release(pos); + } + else + return E_NOTIMPL; + return hr; +} + +static const IMediaPositionVtbl IMediaPositionPassThru_Vtbl = +{ + MediaPositionPassThru_QueryInterface, + MediaPositionPassThru_AddRef, + MediaPositionPassThru_Release, + MediaPositionPassThru_GetTypeInfoCount, + MediaPositionPassThru_GetTypeInfo, + MediaPositionPassThru_GetIDsOfNames, + MediaPositionPassThru_Invoke, + MediaPositionPassThru_get_Duration, + MediaPositionPassThru_put_CurrentPosition, + MediaPositionPassThru_get_CurrentPosition, + MediaPositionPassThru_get_StopTime, + MediaPositionPassThru_put_StopTime, + MediaPositionPassThru_get_PrerollTime, + MediaPositionPassThru_put_PrerollTime, + MediaPositionPassThru_put_Rate, + MediaPositionPassThru_get_Rate, + MediaPositionPassThru_CanSeekForward, + MediaPositionPassThru_CanSeekBackward +}; diff --git a/reactos/lib/3rdparty/strmbase/qualitycontrol.c b/reactos/lib/3rdparty/strmbase/qualitycontrol.c new file mode 100644 index 00000000000..f96ed64a2a2 --- /dev/null +++ b/reactos/lib/3rdparty/strmbase/qualitycontrol.c @@ -0,0 +1,318 @@ +/* + * Quality Control Interfaces + * + * Copyright 2010 Maarten Lankhorst for CodeWeavers + * + * rendering qos functions based on, the original can be found at + * gstreamer/libs/gst/base/gstbasesink.c which has copyright notice: + * + * Copyright (C) 2005-2007 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include "dshow.h" +#include "wine/strmbase.h" +#include "strmbase_private.h" + +#include "uuids.h" +#include "wine/debug.h" + +#include + +WINE_DEFAULT_DEBUG_CHANNEL(strmbase_qc); + +HRESULT QualityControlImpl_Create(IPin *input, IBaseFilter *self, QualityControlImpl **ppv) { + QualityControlImpl *This; + *ppv = HeapAlloc(GetProcessHeap(),0,sizeof(QualityControlImpl)); + if (!*ppv) + return E_OUTOFMEMORY; + This = *ppv; + This->input = input; + This->self = self; + This->tonotify = NULL; + This->clock = NULL; + return S_OK; +} + +HRESULT QualityControlImpl_Destroy(QualityControlImpl *This) +{ + return HeapFree(GetProcessHeap(),0,This); +} + +HRESULT WINAPI QualityControlImpl_QueryInterface(IQualityControl *iface, REFIID riid, void **ppv) { + QualityControlImpl *This = (QualityControlImpl*)iface; + return IBaseFilter_QueryInterface(This->self, riid, ppv); +} + +ULONG WINAPI QualityControlImpl_AddRef(IQualityControl *iface) { + QualityControlImpl *This = (QualityControlImpl*)iface; + return IBaseFilter_AddRef(This->self); +} + +ULONG WINAPI QualityControlImpl_Release(IQualityControl *iface) { + QualityControlImpl *This = (QualityControlImpl*)iface; + return IBaseFilter_Release(This->self); +} + +HRESULT WINAPI QualityControlImpl_Notify(IQualityControl *iface, IBaseFilter *sender, Quality qm) { + HRESULT hr = S_FALSE; + QualityControlImpl *This = (QualityControlImpl*)iface; + if (This->tonotify) + return IQualityControl_Notify(This->tonotify, This->self, qm); + if (This->input) { + IPin *to = NULL; + IPin_ConnectedTo(This->input, &to); + if (to) { + IQualityControl *qc = NULL; + IPin_QueryInterface(to, &IID_IQualityControl, (void**)&qc); + if (qc) { + hr = IQualityControl_Notify(qc, This->self, qm); + IQualityControl_Release(qc); + } + IPin_Release(to); + } + } + return hr; +} + +HRESULT WINAPI QualityControlImpl_SetSink(IQualityControl *iface, IQualityControl *tonotify) { + QualityControlImpl *This = (QualityControlImpl*)iface; + This->tonotify = tonotify; + return S_OK; +} + +/* Macros copied from gstreamer, weighted average between old average and new ones */ +#define DO_RUNNING_AVG(avg,val,size) (((val) + ((size)-1) * (avg)) / (size)) + +/* generic running average, this has a neutral window size */ +#define UPDATE_RUNNING_AVG(avg,val) DO_RUNNING_AVG(avg,val,8) + +/* the windows for these running averages are experimentally obtained. + * possitive values get averaged more while negative values use a small + * window so we can react faster to badness. */ +#define UPDATE_RUNNING_AVG_P(avg,val) DO_RUNNING_AVG(avg,val,16) +#define UPDATE_RUNNING_AVG_N(avg,val) DO_RUNNING_AVG(avg,val,4) + +void QualityControlRender_Start(QualityControlImpl *This, REFERENCE_TIME tStart) { + This->avg_render = This->last_in_time = This->last_left = This->avg_duration = This->avg_pt = -1; + This->clockstart = tStart; + This->avg_rate = -1.0; + This->rendered = This->dropped = This->is_dropped = 0; + This->qos_handled = 1; /* Lie that will be corrected on first adjustment */ +} + + +void QualityControlRender_SetClock(QualityControlImpl *This, IReferenceClock *clock) { + This->clock = clock; +} + +static BOOL QualityControlRender_IsLate(QualityControlImpl *This, REFERENCE_TIME jitter, + REFERENCE_TIME start, REFERENCE_TIME stop) +{ + REFERENCE_TIME max_lateness = 200000; + + /* we can add a valid stop time */ + if (stop >= start) + max_lateness += stop; + else + max_lateness += start; + + /* if the jitter bigger than duration and lateness we are too late */ + if (start + jitter > max_lateness) { + WARN("buffer is too late %i > %i\n", (int)((start + jitter)/10000), (int)(max_lateness/10000)); + /* !!emergency!!, if we did not receive anything valid for more than a + * second, render it anyway so the user sees something */ + if (This->last_in_time < 0 || + start - This->last_in_time < 10000000) + return TRUE; + FIXME("A lot of buffers are being dropped.\n"); + FIXME("There may be a timestamping problem, or this computer is too slow.\n"); + } + This->last_in_time = start; + return FALSE; +} + +HRESULT QualityControlRender_WaitFor(QualityControlImpl *This, IMediaSample *sample, HANDLE ev) { + REFERENCE_TIME start = -1, stop = -1, jitter = 0; + This->current_rstart = This->current_rstop = -1; + This->current_jitter = 0; + if (!This->clock || FAILED(IMediaSample_GetTime(sample, &start, &stop))) + return S_OK; + + if (start >= 0) { + REFERENCE_TIME now; + IReferenceClock_GetTime(This->clock, &now); + now -= This->clockstart; + + jitter = now - start; + if (jitter <= -10000) { + DWORD_PTR cookie; + IReferenceClock_AdviseTime(This->clock, This->clockstart, start, (HEVENT)ev, &cookie); + WaitForSingleObject(ev, INFINITE); + IReferenceClock_Unadvise(This->clock, cookie); + } + } + else + start = stop = -1; + This->current_rstart = start; + This->current_rstop = stop > start ? stop : start; + This->current_jitter = jitter; + This->is_dropped = QualityControlRender_IsLate(This, jitter, start, stop); + TRACE("Dropped: %i %i %i %i\n", This->is_dropped, (int)(start/10000), (int)(stop/10000), (int)(jitter / 10000)); + if (This->is_dropped) { + This->dropped++; + if (!This->qos_handled) + return S_FALSE; + } else + This->rendered++; + return S_OK; +} + +void QualityControlRender_DoQOS(QualityControlImpl *priv) +{ + REFERENCE_TIME start, stop, jitter, pt, entered, left, duration; + double rate; + + if (!priv->clock || priv->current_rstart < 0) + return; + + start = priv->current_rstart; + stop = priv->current_rstop; + jitter = priv->current_jitter; + + if (jitter < 0) { + /* this is the time the buffer entered the sink */ + if (start < -jitter) + entered = 0; + else + entered = start + jitter; + left = start; + } else { + /* this is the time the buffer entered the sink */ + entered = start + jitter; + /* this is the time the buffer left the sink */ + left = start + jitter; + } + + /* calculate duration of the buffer */ + if (stop >= start) + duration = stop - start; + else + duration = 0; + + /* if we have the time when the last buffer left us, calculate + * processing time */ + if (priv->last_left >= 0) { + if (entered > priv->last_left) { + pt = entered - priv->last_left; + } else { + pt = 0; + } + } else { + pt = priv->avg_pt; + } + +#define XTIME(u) (int)(u/10000000), (int)((u / 10000)%1000) + TRACE("start: %u.%03u, entered %u.%03u, left %u.%03u, pt: %u.%03u, " + "duration %u.%03u, jitter %u.%03u\n", XTIME(start), XTIME(entered), + XTIME(left), XTIME(pt), XTIME(duration), XTIME(jitter)); + + TRACE("avg_duration: %u.%03u, avg_pt: %u.%03u, avg_rate: %g\n", + XTIME(priv->avg_duration), XTIME(priv->avg_pt), priv->avg_rate); +#undef XTIME + + /* collect running averages. for first observations, we copy the + * values */ + if (priv->avg_duration < 0) + priv->avg_duration = duration; + else + priv->avg_duration = UPDATE_RUNNING_AVG (priv->avg_duration, duration); + + if (priv->avg_pt < 0) + priv->avg_pt = pt; + else + priv->avg_pt = UPDATE_RUNNING_AVG (priv->avg_pt, pt); + + if (priv->avg_duration != 0) + rate = + (double)priv->avg_pt / + (double)priv->avg_duration; + else + rate = 0.0; + + if (priv->last_left >= 0) { + if (priv->is_dropped || priv->avg_rate < 0.0) { + priv->avg_rate = rate; + } else { + if (rate > 1.0) + priv->avg_rate = UPDATE_RUNNING_AVG_N (priv->avg_rate, rate); + else + priv->avg_rate = UPDATE_RUNNING_AVG_P (priv->avg_rate, rate); + } + } + + if (priv->avg_rate >= 0.0) { + HRESULT hr; + Quality q; + /* if we have a valid rate, start sending QoS messages */ + if (priv->current_jitter < 0) { + /* make sure we never go below 0 when adding the jitter to the + * timestamp. */ + if (priv->current_rstart < -priv->current_jitter) + priv->current_jitter = -priv->current_rstart; + } + else + priv->current_jitter += (priv->current_rstop - priv->current_rstart); + q.Type = (jitter > 0 ? Famine : Flood); + q.Proportion = (LONG)(1000. / priv->avg_rate); + if (q.Proportion < 200) + q.Proportion = 200; + else if (q.Proportion > 5000) + q.Proportion = 5000; + q.Late = priv->current_jitter; + q.TimeStamp = priv->current_rstart; + TRACE("Late: %i from %i, rate: %g\n", (int)(q.Late/10000), (int)(q.TimeStamp/10000), 1./priv->avg_rate); + hr = IQualityControl_Notify((IQualityControl *)priv, priv->self, q); + priv->qos_handled = hr == S_OK; + } + + /* record when this buffer will leave us */ + priv->last_left = left; +} + + +void QualityControlRender_BeginRender(QualityControlImpl *This) { + This->start = -1; + if (!This->clock) + return; + IReferenceClock_GetTime(This->clock, &This->start); +} + +void QualityControlRender_EndRender(QualityControlImpl *This) { + REFERENCE_TIME elapsed; + if (!This->clock || This->start < 0 || FAILED(IReferenceClock_GetTime(This->clock, &This->stop))) + return; + + elapsed = This->start - This->stop; + if (elapsed < 0) + return; + if (This->avg_render < 0) + This->avg_render = elapsed; + else + This->avg_render = UPDATE_RUNNING_AVG (This->avg_render, elapsed); +} diff --git a/reactos/lib/3rdparty/strmbase/renderer.c b/reactos/lib/3rdparty/strmbase/renderer.c new file mode 100644 index 00000000000..8bbb1f81130 --- /dev/null +++ b/reactos/lib/3rdparty/strmbase/renderer.c @@ -0,0 +1,614 @@ +/* + * Generic Implementation of strmbase Base Renderer classes + * + * Copyright 2012 Aric Stewart, CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include "dshow.h" +#include "wine/debug.h" +#include "wine/unicode.h" +#include "wine/strmbase.h" +#include "uuids.h" +#include "vfwmsgs.h" +#include "strmbase_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(strmbase); + +static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0}; +static const WCHAR wcsAltInputPinName[] = {'I','n',0}; + +static inline BaseInputPin *impl_BaseInputPin_from_IPin( IPin *iface ) +{ + return CONTAINING_RECORD(iface, BaseInputPin, pin.IPin_iface); +} + +static inline BaseRenderer *impl_from_IBaseFilter(IBaseFilter *iface) +{ + return CONTAINING_RECORD(iface, BaseRenderer, filter.IBaseFilter_iface); +} + +static inline BaseRenderer *impl_from_BaseFilter(BaseFilter *iface) +{ + return CONTAINING_RECORD(iface, BaseRenderer, filter); +} + +static const IQualityControlVtbl Renderer_QualityControl_Vtbl = { + QualityControlImpl_QueryInterface, + QualityControlImpl_AddRef, + QualityControlImpl_Release, + QualityControlImpl_Notify, + QualityControlImpl_SetSink +}; + +static HRESULT WINAPI BaseRenderer_InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) +{ + BaseInputPin *This = impl_BaseInputPin_from_IPin(iface); + BaseRenderer *renderer = impl_from_IBaseFilter(This->pin.pinInfo.pFilter); + HRESULT hr = S_OK; + + TRACE("(%p/%p)->(%p, %p)\n", This, renderer, pReceivePin, pmt); + + EnterCriticalSection(This->pin.pCritSec); + hr = BaseInputPinImpl_ReceiveConnection(iface, pReceivePin, pmt); + if (SUCCEEDED(hr)) + { + if (renderer->pFuncsTable->pfnCompleteConnect) + hr = renderer->pFuncsTable->pfnCompleteConnect(renderer, pReceivePin); + } + LeaveCriticalSection(This->pin.pCritSec); + + return hr; +} + +static HRESULT WINAPI BaseRenderer_InputPin_Disconnect(IPin * iface) +{ + BaseInputPin *This = impl_BaseInputPin_from_IPin(iface); + BaseRenderer *renderer = impl_from_IBaseFilter(This->pin.pinInfo.pFilter); + HRESULT hr; + + TRACE("(%p/%p)\n", This, renderer); + + EnterCriticalSection(This->pin.pCritSec); + hr = BasePinImpl_Disconnect(iface); + if (SUCCEEDED(hr)) + { + if (renderer->pFuncsTable->pfnBreakConnect) + hr = renderer->pFuncsTable->pfnBreakConnect(renderer); + } + BaseRendererImpl_ClearPendingSample(renderer); + LeaveCriticalSection(This->pin.pCritSec); + + return hr; +} + +static HRESULT WINAPI BaseRenderer_InputPin_EndOfStream(IPin * iface) +{ + HRESULT hr = S_OK; + BaseInputPin* This = impl_BaseInputPin_from_IPin(iface); + BaseRenderer *pFilter = impl_from_IBaseFilter(This->pin.pinInfo.pFilter); + + TRACE("(%p/%p)->()\n", This, pFilter); + + EnterCriticalSection(&pFilter->filter.csFilter); + EnterCriticalSection(&pFilter->csRenderLock); + hr = BaseInputPinImpl_EndOfStream(iface); + EnterCriticalSection(This->pin.pCritSec); + if (SUCCEEDED(hr)) + { + if (pFilter->pFuncsTable->pfnEndOfStream) + hr = pFilter->pFuncsTable->pfnEndOfStream(pFilter); + else + hr = BaseRendererImpl_EndOfStream(pFilter); + } + LeaveCriticalSection(This->pin.pCritSec); + LeaveCriticalSection(&pFilter->csRenderLock); + LeaveCriticalSection(&pFilter->filter.csFilter); + return hr; +} + +static HRESULT WINAPI BaseRenderer_InputPin_BeginFlush(IPin * iface) +{ + BaseInputPin* This = impl_BaseInputPin_from_IPin(iface); + BaseRenderer *pFilter = impl_from_IBaseFilter(This->pin.pinInfo.pFilter); + HRESULT hr = S_OK; + + TRACE("(%p/%p)->()\n", This, iface); + + EnterCriticalSection(&pFilter->filter.csFilter); + EnterCriticalSection(&pFilter->csRenderLock); + EnterCriticalSection(This->pin.pCritSec); + hr = BaseInputPinImpl_BeginFlush(iface); + if (SUCCEEDED(hr)) + { + if (pFilter->pFuncsTable->pfnBeginFlush) + hr = pFilter->pFuncsTable->pfnBeginFlush(pFilter); + else + hr = BaseRendererImpl_BeginFlush(pFilter); + } + LeaveCriticalSection(This->pin.pCritSec); + LeaveCriticalSection(&pFilter->filter.csFilter); + LeaveCriticalSection(&pFilter->csRenderLock); + return hr; +} + +static HRESULT WINAPI BaseRenderer_InputPin_EndFlush(IPin * iface) +{ + BaseInputPin* This = impl_BaseInputPin_from_IPin(iface); + BaseRenderer *pFilter = impl_from_IBaseFilter(This->pin.pinInfo.pFilter); + HRESULT hr = S_OK; + + TRACE("(%p/%p)->()\n", This, pFilter); + + EnterCriticalSection(&pFilter->filter.csFilter); + EnterCriticalSection(&pFilter->csRenderLock); + EnterCriticalSection(This->pin.pCritSec); + hr = BaseInputPinImpl_EndFlush(iface); + if (SUCCEEDED(hr)) + { + if (pFilter->pFuncsTable->pfnEndFlush) + hr = pFilter->pFuncsTable->pfnEndFlush(pFilter); + else + hr = BaseRendererImpl_EndFlush(pFilter); + } + LeaveCriticalSection(This->pin.pCritSec); + LeaveCriticalSection(&pFilter->csRenderLock); + LeaveCriticalSection(&pFilter->filter.csFilter); + return hr; +} + +static const IPinVtbl BaseRenderer_InputPin_Vtbl = +{ + BaseInputPinImpl_QueryInterface, + BasePinImpl_AddRef, + BaseInputPinImpl_Release, + BaseInputPinImpl_Connect, + BaseRenderer_InputPin_ReceiveConnection, + BaseRenderer_InputPin_Disconnect, + BasePinImpl_ConnectedTo, + BasePinImpl_ConnectionMediaType, + BasePinImpl_QueryPinInfo, + BasePinImpl_QueryDirection, + BasePinImpl_QueryId, + BaseInputPinImpl_QueryAccept, + BasePinImpl_EnumMediaTypes, + BasePinImpl_QueryInternalConnections, + BaseRenderer_InputPin_EndOfStream, + BaseRenderer_InputPin_BeginFlush, + BaseRenderer_InputPin_EndFlush, + BaseInputPinImpl_NewSegment +}; + +static IPin* WINAPI BaseRenderer_GetPin(BaseFilter *iface, int pos) +{ + BaseRenderer *This = impl_from_BaseFilter(iface); + + if (pos >= 1 || pos < 0) + return NULL; + + IPin_AddRef(&This->pInputPin->pin.IPin_iface); + return &This->pInputPin->pin.IPin_iface; +} + +static LONG WINAPI BaseRenderer_GetPinCount(BaseFilter *iface) +{ + return 1; +} + +static HRESULT WINAPI BaseRenderer_Input_CheckMediaType(BasePin *pin, const AM_MEDIA_TYPE * pmt) +{ + BaseRenderer *This = impl_from_IBaseFilter(pin->pinInfo.pFilter); + return This->pFuncsTable->pfnCheckMediaType(This, pmt); +} + +static HRESULT WINAPI BaseRenderer_Receive(BaseInputPin *pin, IMediaSample * pSample) +{ + BaseRenderer *This = impl_from_IBaseFilter(pin->pin.pinInfo.pFilter); + return BaseRendererImpl_Receive(This, pSample); +} + +static const BaseFilterFuncTable RendererBaseFilterFuncTable = { + BaseRenderer_GetPin, + BaseRenderer_GetPinCount +}; + +static const BasePinFuncTable input_BaseFuncTable = { + BaseRenderer_Input_CheckMediaType, + NULL, + BasePinImpl_GetMediaTypeVersion, + BasePinImpl_GetMediaType +}; + +static const BaseInputPinFuncTable input_BaseInputFuncTable = { + BaseRenderer_Receive +}; + + +HRESULT WINAPI BaseRenderer_Init(BaseRenderer * This, const IBaseFilterVtbl *Vtbl, IUnknown *pUnkOuter, const CLSID *pClsid, DWORD_PTR DebugInfo, const BaseRendererFuncTable* pBaseFuncsTable) +{ + PIN_INFO piInput; + HRESULT hr; + + BaseFilter_Init(&This->filter, Vtbl, pClsid, DebugInfo, &RendererBaseFilterFuncTable); + + This->pFuncsTable = pBaseFuncsTable; + + /* construct input pin */ + piInput.dir = PINDIR_INPUT; + piInput.pFilter = &This->filter.IBaseFilter_iface; + lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0])); + + hr = BaseInputPin_Construct(&BaseRenderer_InputPin_Vtbl, &piInput, &input_BaseFuncTable, &input_BaseInputFuncTable, &This->filter.csFilter, NULL, (IPin **)&This->pInputPin); + + if (SUCCEEDED(hr)) + { + hr = CreatePosPassThru(pUnkOuter ? pUnkOuter: (IUnknown*)This, TRUE, &This->pInputPin->pin.IPin_iface, &This->pPosition); + if (FAILED(hr)) + return hr; + + InitializeCriticalSection(&This->csRenderLock); + This->csRenderLock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__": BaseRenderer.csRenderLock"); + This->evComplete = CreateEventW(NULL, TRUE, TRUE, NULL); + This->ThreadSignal = CreateEventW(NULL, TRUE, TRUE, NULL); + This->RenderEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + This->pMediaSample = NULL; + + QualityControlImpl_Create(&This->pInputPin->pin.IPin_iface, &This->filter.IBaseFilter_iface, &This->qcimpl); + This->qcimpl->IQualityControl_iface.lpVtbl = &Renderer_QualityControl_Vtbl; + } + + return hr; +} + +HRESULT WINAPI BaseRendererImpl_QueryInterface(IBaseFilter* iface, REFIID riid, LPVOID * ppv) +{ + BaseRenderer *This = impl_from_IBaseFilter(iface); + + if (IsEqualIID(riid, &IID_IMediaSeeking) || IsEqualIID(riid, &IID_IMediaPosition)) + return IUnknown_QueryInterface(This->pPosition, riid, ppv); + else if (IsEqualIID(riid, &IID_IQualityControl)) + { + *ppv = &This->qcimpl->IQualityControl_iface; + IUnknown_AddRef((IUnknown *)(*ppv)); + return S_OK; + } + else + return BaseFilterImpl_QueryInterface(iface, riid, ppv); +} + +ULONG WINAPI BaseRendererImpl_Release(IBaseFilter* iface) +{ + BaseRenderer *This = impl_from_IBaseFilter(iface); + ULONG refCount = BaseFilterImpl_Release(iface); + + if (!refCount) + { + IPin *pConnectedTo; + + if (SUCCEEDED(IPin_ConnectedTo(&This->pInputPin->pin.IPin_iface, &pConnectedTo))) + { + IPin_Disconnect(pConnectedTo); + IPin_Release(pConnectedTo); + } + IPin_Disconnect(&This->pInputPin->pin.IPin_iface); + IPin_Release(&This->pInputPin->pin.IPin_iface); + + if (This->pPosition) + IUnknown_Release(This->pPosition); + + This->csRenderLock.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&This->csRenderLock); + + BaseRendererImpl_ClearPendingSample(This); + CloseHandle(This->evComplete); + CloseHandle(This->ThreadSignal); + CloseHandle(This->RenderEvent); + QualityControlImpl_Destroy(This->qcimpl); + } + return refCount; +} + +HRESULT WINAPI BaseRendererImpl_Receive(BaseRenderer *This, IMediaSample * pSample) +{ + HRESULT hr = S_OK; + REFERENCE_TIME start, stop; + AM_MEDIA_TYPE *pmt; + + TRACE("(%p)->%p\n", This, pSample); + + if (This->pInputPin->end_of_stream || This->pInputPin->flushing) + return S_FALSE; + + if (This->filter.state == State_Stopped) + return VFW_E_WRONG_STATE; + + if (IMediaSample_GetMediaType(pSample, &pmt) == S_OK) + { + if (FAILED(This->pFuncsTable->pfnCheckMediaType(This, pmt))) + { + return VFW_E_TYPE_NOT_ACCEPTED; + } + } + + This->pMediaSample = pSample; + IMediaSample_AddRef(pSample); + + if (This->pFuncsTable->pfnPrepareReceive) + hr = This->pFuncsTable->pfnPrepareReceive(This, pSample); + if (FAILED(hr)) + { + if (hr == VFW_E_SAMPLE_REJECTED) + return S_OK; + else + return hr; + } + + if (This->pFuncsTable->pfnPrepareRender) + This->pFuncsTable->pfnPrepareRender(This); + + EnterCriticalSection(&This->csRenderLock); + if ( This->filter.state == State_Paused ) + { + if (This->pFuncsTable->pfnOnReceiveFirstSample) + This->pFuncsTable->pfnOnReceiveFirstSample(This, pSample); + + SetEvent(This->evComplete); + } + + /* Wait for render Time */ + if (SUCCEEDED(IMediaSample_GetTime(pSample, &start, &stop))) + { + hr = S_FALSE; + RendererPosPassThru_RegisterMediaTime(This->pPosition, start); + if (This->pFuncsTable->pfnShouldDrawSampleNow) + hr = This->pFuncsTable->pfnShouldDrawSampleNow(This, pSample, &start, &stop); + + if (hr == S_OK) + ;/* Do not wait: drop through */ + else if (hr == S_FALSE) + { + if (This->pFuncsTable->pfnOnWaitStart) + This->pFuncsTable->pfnOnWaitStart(This); + + LeaveCriticalSection(&This->csRenderLock); + hr = QualityControlRender_WaitFor(This->qcimpl, pSample, This->RenderEvent); + EnterCriticalSection(&This->csRenderLock); + + if (This->pFuncsTable->pfnOnWaitEnd) + This->pFuncsTable->pfnOnWaitEnd(This); + } + else + { + LeaveCriticalSection(&This->csRenderLock); + /* Drop Sample */ + return S_OK; + } + } + + if (SUCCEEDED(hr)) + { + QualityControlRender_BeginRender(This->qcimpl); + hr = This->pFuncsTable->pfnDoRenderSample(This, pSample); + QualityControlRender_EndRender(This->qcimpl); + } + + QualityControlRender_DoQOS(This->qcimpl); + + BaseRendererImpl_ClearPendingSample(This); + LeaveCriticalSection(&This->csRenderLock); + + return hr; +} + +HRESULT WINAPI BaseRendererImpl_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin) +{ + BaseRenderer *This = impl_from_IBaseFilter(iface); + + TRACE("(%p)->(%s,%p)\n", This, debugstr_w(Id), ppPin); + + if (!Id || !ppPin) + return E_POINTER; + + if (!lstrcmpiW(Id,wcsInputPinName) || !lstrcmpiW(Id,wcsAltInputPinName)) + { + *ppPin = &This->pInputPin->pin.IPin_iface; + IPin_AddRef(*ppPin); + return S_OK; + } + *ppPin = NULL; + return VFW_E_NOT_FOUND; +} + +HRESULT WINAPI BaseRendererImpl_Stop(IBaseFilter * iface) +{ + BaseRenderer *This = impl_from_IBaseFilter(iface); + + TRACE("(%p)->()\n", This); + + EnterCriticalSection(&This->csRenderLock); + { + RendererPosPassThru_ResetMediaTime(This->pPosition); + if (This->pFuncsTable->pfnOnStopStreaming) + This->pFuncsTable->pfnOnStopStreaming(This); + This->filter.state = State_Stopped; + SetEvent(This->evComplete); + SetEvent(This->ThreadSignal); + SetEvent(This->RenderEvent); + } + LeaveCriticalSection(&This->csRenderLock); + + return S_OK; +} + +HRESULT WINAPI BaseRendererImpl_Run(IBaseFilter * iface, REFERENCE_TIME tStart) +{ + HRESULT hr = S_OK; + BaseRenderer *This = impl_from_IBaseFilter(iface); + TRACE("(%p)->(%s)\n", This, wine_dbgstr_longlong(tStart)); + + EnterCriticalSection(&This->csRenderLock); + This->filter.rtStreamStart = tStart; + if (This->filter.state == State_Running) + goto out; + + SetEvent(This->evComplete); + ResetEvent(This->ThreadSignal); + + if (This->pInputPin->pin.pConnectedTo) + { + This->pInputPin->end_of_stream = 0; + } + else if (This->filter.filterInfo.pGraph) + { + IMediaEventSink *pEventSink; + hr = IFilterGraph_QueryInterface(This->filter.filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink); + if (SUCCEEDED(hr)) + { + hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, (LONG_PTR)This); + IMediaEventSink_Release(pEventSink); + } + hr = S_OK; + } + if (SUCCEEDED(hr)) + { + QualityControlRender_Start(This->qcimpl, This->filter.rtStreamStart); + if (This->pFuncsTable->pfnOnStartStreaming) + This->pFuncsTable->pfnOnStartStreaming(This); + if (This->filter.state == State_Stopped) + BaseRendererImpl_ClearPendingSample(This); + SetEvent(This->RenderEvent); + This->filter.state = State_Running; + } +out: + LeaveCriticalSection(&This->csRenderLock); + + return hr; +} + +HRESULT WINAPI BaseRendererImpl_Pause(IBaseFilter * iface) +{ + BaseRenderer *This = impl_from_IBaseFilter(iface); + + TRACE("(%p)->()\n", This); + + EnterCriticalSection(&This->csRenderLock); + { + if (This->filter.state != State_Paused) + { + if (This->filter.state == State_Stopped) + { + if (This->pInputPin->pin.pConnectedTo) + ResetEvent(This->evComplete); + This->pInputPin->end_of_stream = 0; + } + else if (This->pFuncsTable->pfnOnStopStreaming) + This->pFuncsTable->pfnOnStopStreaming(This); + + if (This->filter.state == State_Stopped) + BaseRendererImpl_ClearPendingSample(This); + ResetEvent(This->RenderEvent); + This->filter.state = State_Paused; + } + } + ResetEvent(This->ThreadSignal); + LeaveCriticalSection(&This->csRenderLock); + + return S_OK; +} + +HRESULT WINAPI BaseRendererImpl_SetSyncSource(IBaseFilter *iface, IReferenceClock *clock) +{ + BaseRenderer *This = impl_from_IBaseFilter(iface); + HRESULT hr; + + EnterCriticalSection(&This->filter.csFilter); + QualityControlRender_SetClock(This->qcimpl, clock); + hr = BaseFilterImpl_SetSyncSource(iface, clock); + LeaveCriticalSection(&This->filter.csFilter); + return hr; +} + + +HRESULT WINAPI BaseRendererImpl_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState) +{ + HRESULT hr; + BaseRenderer *This = impl_from_IBaseFilter(iface); + + TRACE("(%p)->(%d, %p)\n", This, dwMilliSecsTimeout, pState); + + if (WaitForSingleObject(This->evComplete, dwMilliSecsTimeout) == WAIT_TIMEOUT) + hr = VFW_S_STATE_INTERMEDIATE; + else + hr = S_OK; + + BaseFilterImpl_GetState(iface, dwMilliSecsTimeout, pState); + + return hr; +} + +HRESULT WINAPI BaseRendererImpl_EndOfStream(BaseRenderer* iface) +{ + IMediaEventSink* pEventSink; + IFilterGraph *graph; + HRESULT hr = S_OK; + + TRACE("(%p)\n", iface); + + graph = iface->filter.filterInfo.pGraph; + if (graph) + { hr = IFilterGraph_QueryInterface(iface->filter.filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink); + if (SUCCEEDED(hr)) + { + hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, (LONG_PTR)iface); + IMediaEventSink_Release(pEventSink); + } + } + RendererPosPassThru_EOS(iface->pPosition); + SetEvent(iface->evComplete); + + return hr; +} + +HRESULT WINAPI BaseRendererImpl_BeginFlush(BaseRenderer* iface) +{ + TRACE("(%p)\n", iface); + BaseRendererImpl_ClearPendingSample(iface); + SetEvent(iface->ThreadSignal); + SetEvent(iface->RenderEvent); + return S_OK; +} + +HRESULT WINAPI BaseRendererImpl_EndFlush(BaseRenderer* iface) +{ + TRACE("(%p)\n", iface); + QualityControlRender_Start(iface->qcimpl, iface->filter.rtStreamStart); + RendererPosPassThru_ResetMediaTime(iface->pPosition); + ResetEvent(iface->ThreadSignal); + ResetEvent(iface->RenderEvent); + return S_OK; +} + +HRESULT WINAPI BaseRendererImpl_ClearPendingSample(BaseRenderer *iface) +{ + if (iface->pMediaSample) + { + IMediaSample_Release(iface->pMediaSample); + iface->pMediaSample = NULL; + } + return S_OK; +} diff --git a/reactos/lib/3rdparty/strmbase/seeking.c b/reactos/lib/3rdparty/strmbase/seeking.c new file mode 100644 index 00000000000..c31699c2099 --- /dev/null +++ b/reactos/lib/3rdparty/strmbase/seeking.c @@ -0,0 +1,325 @@ +/* + * Filter Seeking and Control Interfaces + * + * Copyright 2003 Robert Shearman + * Copyright 2010 Aric Stewart, CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +/* FIXME: critical sections */ + +#define COBJMACROS + +#include "dshow.h" +#include "wine/strmbase.h" + +#include "uuids.h" +#include "wine/debug.h" + +#include + +WINE_DEFAULT_DEBUG_CHANNEL(strmbase); + +static inline SourceSeeking *impl_from_IMediaSeeking(IMediaSeeking *iface) +{ + return CONTAINING_RECORD(iface, SourceSeeking, IMediaSeeking_iface); +} + +HRESULT SourceSeeking_Init(SourceSeeking *pSeeking, const IMediaSeekingVtbl *Vtbl, SourceSeeking_ChangeStop fnChangeStop, SourceSeeking_ChangeStart fnChangeStart, SourceSeeking_ChangeRate fnChangeRate, PCRITICAL_SECTION crit_sect) +{ + assert(fnChangeStop && fnChangeStart && fnChangeRate); + + pSeeking->IMediaSeeking_iface.lpVtbl = Vtbl; + pSeeking->refCount = 1; + pSeeking->fnChangeRate = fnChangeRate; + pSeeking->fnChangeStop = fnChangeStop; + pSeeking->fnChangeStart = fnChangeStart; + pSeeking->dwCapabilities = AM_SEEKING_CanSeekForwards | + AM_SEEKING_CanSeekBackwards | + AM_SEEKING_CanSeekAbsolute | + AM_SEEKING_CanGetStopPos | + AM_SEEKING_CanGetDuration; + pSeeking->llCurrent = 0; + pSeeking->llStop = ((ULONGLONG)0x80000000) << 32; + pSeeking->llDuration = pSeeking->llStop; + pSeeking->dRate = 1.0; + pSeeking->timeformat = TIME_FORMAT_MEDIA_TIME; + pSeeking->crst = crit_sect; + return S_OK; +} + +HRESULT WINAPI SourceSeekingImpl_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities) +{ + SourceSeeking *This = impl_from_IMediaSeeking(iface); + + TRACE("(%p)\n", pCapabilities); + + *pCapabilities = This->dwCapabilities; + + return S_OK; +} + +HRESULT WINAPI SourceSeekingImpl_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities) +{ + SourceSeeking *This = impl_from_IMediaSeeking(iface); + HRESULT hr; + DWORD dwCommonCaps; + + TRACE("(%p)\n", pCapabilities); + + if (!pCapabilities) + return E_POINTER; + + dwCommonCaps = *pCapabilities & This->dwCapabilities; + + if (!dwCommonCaps) + hr = E_FAIL; + else + hr = (*pCapabilities == dwCommonCaps) ? S_OK : S_FALSE; + *pCapabilities = dwCommonCaps; + return hr; +} + +HRESULT WINAPI SourceSeekingImpl_IsFormatSupported(IMediaSeeking * iface, const GUID * pFormat) +{ + TRACE("(%s)\n", debugstr_guid(pFormat)); + + return (IsEqualIID(pFormat, &TIME_FORMAT_MEDIA_TIME) ? S_OK : S_FALSE); +} + +HRESULT WINAPI SourceSeekingImpl_QueryPreferredFormat(IMediaSeeking * iface, GUID * pFormat) +{ + TRACE("(%s)\n", debugstr_guid(pFormat)); + + *pFormat = TIME_FORMAT_MEDIA_TIME; + return S_OK; +} + +HRESULT WINAPI SourceSeekingImpl_GetTimeFormat(IMediaSeeking * iface, GUID * pFormat) +{ + SourceSeeking *This = impl_from_IMediaSeeking(iface); + TRACE("(%s)\n", debugstr_guid(pFormat)); + + EnterCriticalSection(This->crst); + *pFormat = This->timeformat; + LeaveCriticalSection(This->crst); + + return S_OK; +} + +HRESULT WINAPI SourceSeekingImpl_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat) +{ + SourceSeeking *This = impl_from_IMediaSeeking(iface); + HRESULT hr = S_OK; + + TRACE("(%s)\n", debugstr_guid(pFormat)); + + EnterCriticalSection(This->crst); + if (!IsEqualIID(pFormat, &This->timeformat)) + hr = S_FALSE; + LeaveCriticalSection(This->crst); + + return hr; +} + +HRESULT WINAPI SourceSeekingImpl_SetTimeFormat(IMediaSeeking * iface, const GUID * pFormat) +{ + SourceSeeking *This = impl_from_IMediaSeeking(iface); + TRACE("%p %s\n", This, debugstr_guid(pFormat)); + return (IsEqualIID(pFormat, &TIME_FORMAT_MEDIA_TIME) ? S_OK : E_INVALIDARG); +} + + +HRESULT WINAPI SourceSeekingImpl_GetDuration(IMediaSeeking * iface, LONGLONG * pDuration) +{ + SourceSeeking *This = impl_from_IMediaSeeking(iface); + + TRACE("(%p)\n", pDuration); + + EnterCriticalSection(This->crst); + *pDuration = This->llDuration; + LeaveCriticalSection(This->crst); + + return S_OK; +} + +HRESULT WINAPI SourceSeekingImpl_GetStopPosition(IMediaSeeking * iface, LONGLONG * pStop) +{ + SourceSeeking *This = impl_from_IMediaSeeking(iface); + + TRACE("(%p)\n", pStop); + + EnterCriticalSection(This->crst); + *pStop = This->llStop; + LeaveCriticalSection(This->crst); + + return S_OK; +} + +/* FIXME: Make use of the info the filter should expose */ +HRESULT WINAPI SourceSeekingImpl_GetCurrentPosition(IMediaSeeking * iface, LONGLONG * pCurrent) +{ + SourceSeeking *This = impl_from_IMediaSeeking(iface); + + TRACE("(%p)\n", pCurrent); + + EnterCriticalSection(This->crst); + *pCurrent = This->llCurrent; + LeaveCriticalSection(This->crst); + + return S_OK; +} + +HRESULT WINAPI SourceSeekingImpl_ConvertTimeFormat(IMediaSeeking * iface, LONGLONG * pTarget, const GUID * pTargetFormat, LONGLONG Source, const GUID * pSourceFormat) +{ + SourceSeeking *This = impl_from_IMediaSeeking(iface); + if (!pTargetFormat) + pTargetFormat = &This->timeformat; + if (!pSourceFormat) + pSourceFormat = &This->timeformat; + if (IsEqualIID(pTargetFormat, &TIME_FORMAT_MEDIA_TIME) && IsEqualIID(pSourceFormat, &TIME_FORMAT_MEDIA_TIME)) + { + *pTarget = Source; + return S_OK; + } + /* FIXME: clear pTarget? */ + return E_INVALIDARG; +} + +static inline LONGLONG Adjust(LONGLONG value, const LONGLONG * pModifier, DWORD dwFlags) +{ + switch (dwFlags & AM_SEEKING_PositioningBitsMask) + { + case AM_SEEKING_NoPositioning: + return value; + case AM_SEEKING_AbsolutePositioning: + return *pModifier; + case AM_SEEKING_RelativePositioning: + case AM_SEEKING_IncrementalPositioning: + return value + *pModifier; + default: + assert(FALSE); + return 0; + } +} + +HRESULT WINAPI SourceSeekingImpl_SetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, DWORD dwCurrentFlags, LONGLONG * pStop, DWORD dwStopFlags) +{ + SourceSeeking *This = impl_from_IMediaSeeking(iface); + BOOL bChangeCurrent = FALSE, bChangeStop = FALSE; + LONGLONG llNewCurrent, llNewStop; + + TRACE("(%p, %x, %p, %x)\n", pCurrent, dwCurrentFlags, pStop, dwStopFlags); + EnterCriticalSection(This->crst); + + llNewCurrent = Adjust(This->llCurrent, pCurrent, dwCurrentFlags); + llNewStop = Adjust(This->llStop, pStop, dwStopFlags); + + if (pCurrent) + bChangeCurrent = TRUE; + if (llNewStop != This->llStop) + bChangeStop = TRUE; + + TRACE("Old: %u, New: %u\n", (DWORD)(This->llCurrent/10000000), (DWORD)(llNewCurrent/10000000)); + + This->llCurrent = llNewCurrent; + This->llStop = llNewStop; + + if (pCurrent && (dwCurrentFlags & AM_SEEKING_ReturnTime)) + *pCurrent = llNewCurrent; + if (pStop && (dwStopFlags & AM_SEEKING_ReturnTime)) + *pStop = llNewStop; + LeaveCriticalSection(This->crst); + + if (bChangeCurrent) + This->fnChangeStart(iface); + if (bChangeStop) + This->fnChangeStop(iface); + + return S_OK; +} + +HRESULT WINAPI SourceSeekingImpl_GetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, LONGLONG * pStop) +{ + SourceSeeking *This = impl_from_IMediaSeeking(iface); + + TRACE("(%p, %p)\n", pCurrent, pStop); + + EnterCriticalSection(This->crst); + IMediaSeeking_GetCurrentPosition(iface, pCurrent); + IMediaSeeking_GetStopPosition(iface, pStop); + LeaveCriticalSection(This->crst); + + return S_OK; +} + +HRESULT WINAPI SourceSeekingImpl_GetAvailable(IMediaSeeking * iface, LONGLONG * pEarliest, LONGLONG * pLatest) +{ + SourceSeeking *This = impl_from_IMediaSeeking(iface); + + TRACE("(%p, %p)\n", pEarliest, pLatest); + + EnterCriticalSection(This->crst); + *pEarliest = 0; + *pLatest = This->llDuration; + LeaveCriticalSection(This->crst); + + return S_OK; +} + +HRESULT WINAPI SourceSeekingImpl_SetRate(IMediaSeeking * iface, double dRate) +{ + SourceSeeking *This = impl_from_IMediaSeeking(iface); + BOOL bChangeRate = (dRate != This->dRate); + HRESULT hr = S_OK; + + TRACE("(%e)\n", dRate); + + if (dRate > 100 || dRate < .001) + { + FIXME("Excessive rate %e, ignoring\n", dRate); + return VFW_E_UNSUPPORTED_AUDIO; + } + + EnterCriticalSection(This->crst); + This->dRate = dRate; + if (bChangeRate) + hr = This->fnChangeRate(iface); + LeaveCriticalSection(This->crst); + + return hr; +} + +HRESULT WINAPI SourceSeekingImpl_GetRate(IMediaSeeking * iface, double * dRate) +{ + SourceSeeking *This = impl_from_IMediaSeeking(iface); + + TRACE("(%p)\n", dRate); + + EnterCriticalSection(This->crst); + /* Forward? */ + *dRate = This->dRate; + LeaveCriticalSection(This->crst); + + return S_OK; +} + +HRESULT WINAPI SourceSeekingImpl_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll) +{ + TRACE("(%p)\n", pPreroll); + + *pPreroll = 0; + return S_OK; +} diff --git a/reactos/lib/3rdparty/strmbase/strmbase_private.h b/reactos/lib/3rdparty/strmbase/strmbase_private.h new file mode 100644 index 00000000000..6363bf5307d --- /dev/null +++ b/reactos/lib/3rdparty/strmbase/strmbase_private.h @@ -0,0 +1,50 @@ +/* + * Header file for private strmbase implementations + * + * Copyright 2012 Aric Stewart, CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* Quality Control */ +typedef struct QualityControlImpl { + IQualityControl IQualityControl_iface; + IPin *input; + IBaseFilter *self; + IQualityControl *tonotify; + + /* Render stuff */ + IReferenceClock *clock; + REFERENCE_TIME last_in_time, last_left, avg_duration, avg_pt, avg_render, start, stop; + REFERENCE_TIME current_jitter, current_rstart, current_rstop, clockstart; + double avg_rate; + LONG64 rendered, dropped; + BOOL qos_handled, is_dropped; +} QualityControlImpl; + +HRESULT QualityControlImpl_Create(IPin *input, IBaseFilter *self, QualityControlImpl **ppv); +HRESULT QualityControlImpl_Destroy(QualityControlImpl *This); +HRESULT WINAPI QualityControlImpl_QueryInterface(IQualityControl *iface, REFIID riid, void **ppv); +ULONG WINAPI QualityControlImpl_AddRef(IQualityControl *iface); +ULONG WINAPI QualityControlImpl_Release(IQualityControl *iface); +HRESULT WINAPI QualityControlImpl_Notify(IQualityControl *iface, IBaseFilter *sender, Quality qm); +HRESULT WINAPI QualityControlImpl_SetSink(IQualityControl *iface, IQualityControl *tonotify); + +void QualityControlRender_Start(QualityControlImpl *This, REFERENCE_TIME tStart); +void QualityControlRender_SetClock(QualityControlImpl *This, IReferenceClock *clock); +HRESULT QualityControlRender_WaitFor(QualityControlImpl *This, IMediaSample *sample, HANDLE ev); +void QualityControlRender_DoQOS(QualityControlImpl *priv); +void QualityControlRender_BeginRender(QualityControlImpl *This); +void QualityControlRender_EndRender(QualityControlImpl *This); diff --git a/reactos/lib/3rdparty/strmbase/transform.c b/reactos/lib/3rdparty/strmbase/transform.c new file mode 100644 index 00000000000..0e014b07756 --- /dev/null +++ b/reactos/lib/3rdparty/strmbase/transform.c @@ -0,0 +1,641 @@ +/* + * Transform Filter (Base for decoders, etc...) + * + * Copyright 2005 Christian Costa + * Copyright 2010 Aric Stewart, CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#include "config.h" +#include + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "dshow.h" +#include "amvideo.h" +#include "strmif.h" +#include "vfw.h" + +#include + +#include "wine/unicode.h" +#include "wine/debug.h" +#include "wine/strmbase.h" +#include "strmbase_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(strmbase); + +static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0}; +static const WCHAR wcsOutputPinName[] = {'o','u','t','p','u','t',' ','p','i','n',0}; + +static const IBaseFilterVtbl TransformFilter_Vtbl; +static const IPinVtbl TransformFilter_InputPin_Vtbl; +static const IPinVtbl TransformFilter_OutputPin_Vtbl; +static const IQualityControlVtbl TransformFilter_QualityControl_Vtbl; + +static inline BaseInputPin *impl_BaseInputPin_from_BasePin( BasePin *iface ) +{ + return CONTAINING_RECORD(iface, BaseInputPin, pin); +} + +static inline BasePin *impl_BasePin_from_IPin( IPin *iface ) +{ + return CONTAINING_RECORD(iface, BasePin, IPin_iface); +} + +static inline BaseInputPin *impl_BaseInputPin_from_IPin( IPin *iface ) +{ + return CONTAINING_RECORD(iface, BaseInputPin, pin.IPin_iface); +} + +static inline BaseOutputPin *impl_BaseOutputPin_from_IPin( IPin *iface ) +{ + return CONTAINING_RECORD(iface, BaseOutputPin, pin.IPin_iface); +} + +static inline TransformFilter *impl_from_IBaseFilter( IBaseFilter *iface ) +{ + return CONTAINING_RECORD(iface, TransformFilter, filter.IBaseFilter_iface); +} + +static inline TransformFilter *impl_from_BaseFilter( BaseFilter *iface ) +{ + return CONTAINING_RECORD(iface, TransformFilter, filter); +} + +static HRESULT WINAPI TransformFilter_Input_CheckMediaType(BasePin *iface, const AM_MEDIA_TYPE * pmt) +{ + BaseInputPin* This = impl_BaseInputPin_from_BasePin(iface); + TransformFilter * pTransform; + + TRACE("%p\n", iface); + pTransform = impl_from_IBaseFilter(This->pin.pinInfo.pFilter); + + if (pTransform->pFuncsTable->pfnCheckInputType) + return pTransform->pFuncsTable->pfnCheckInputType(pTransform, pmt); + /* Assume OK if there's no query method (the connection will fail if + needed) */ + return S_OK; +} + +static HRESULT WINAPI TransformFilter_Input_Receive(BaseInputPin *This, IMediaSample *pInSample) +{ + HRESULT hr = S_FALSE; + TransformFilter * pTransform; + TRACE("%p\n", This); + pTransform = impl_from_IBaseFilter(This->pin.pinInfo.pFilter); + + EnterCriticalSection(&pTransform->csReceive); + if (pTransform->filter.state == State_Stopped) + { + LeaveCriticalSection(&pTransform->csReceive); + return VFW_E_WRONG_STATE; + } + + if (This->end_of_stream || This->flushing) + { + LeaveCriticalSection(&pTransform->csReceive); + return S_FALSE; + } + + LeaveCriticalSection(&pTransform->csReceive); + if (pTransform->pFuncsTable->pfnReceive) + hr = pTransform->pFuncsTable->pfnReceive(pTransform, pInSample); + else + hr = S_FALSE; + + return hr; +} + +static HRESULT WINAPI TransformFilter_Output_QueryAccept(IPin *iface, const AM_MEDIA_TYPE * pmt) +{ + BasePin *This = impl_BasePin_from_IPin(iface); + TransformFilter *pTransformFilter = impl_from_IBaseFilter(This->pinInfo.pFilter); + AM_MEDIA_TYPE* outpmt = &pTransformFilter->pmt; + TRACE("%p\n", iface); + + if (IsEqualIID(&pmt->majortype, &outpmt->majortype) + && (IsEqualIID(&pmt->subtype, &outpmt->subtype) || IsEqualIID(&outpmt->subtype, &GUID_NULL))) + return S_OK; + return S_FALSE; +} + +static HRESULT WINAPI TransformFilter_Output_DecideBufferSize(BaseOutputPin *This, IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest) +{ + TransformFilter *pTransformFilter = impl_from_IBaseFilter(This->pin.pinInfo.pFilter); + return pTransformFilter->pFuncsTable->pfnDecideBufferSize(pTransformFilter, pAlloc, ppropInputRequest); +} + +static HRESULT WINAPI TransformFilter_Output_GetMediaType(BasePin *This, int iPosition, AM_MEDIA_TYPE *pmt) +{ + TransformFilter *pTransform = impl_from_IBaseFilter(This->pinInfo.pFilter); + + if (iPosition < 0) + return E_INVALIDARG; + if (iPosition > 0) + return VFW_S_NO_MORE_ITEMS; + CopyMediaType(pmt, &pTransform->pmt); + return S_OK; +} + +static IPin* WINAPI TransformFilter_GetPin(BaseFilter *iface, int pos) +{ + TransformFilter *This = impl_from_BaseFilter(iface); + + if (pos >= This->npins || pos < 0) + return NULL; + + IPin_AddRef(This->ppPins[pos]); + return This->ppPins[pos]; +} + +static LONG WINAPI TransformFilter_GetPinCount(BaseFilter *iface) +{ + TransformFilter *This = impl_from_BaseFilter(iface); + + return (This->npins+1); +} + +static const BaseFilterFuncTable tfBaseFuncTable = { + TransformFilter_GetPin, + TransformFilter_GetPinCount +}; + +static const BasePinFuncTable tf_input_BaseFuncTable = { + TransformFilter_Input_CheckMediaType, + NULL, + BasePinImpl_GetMediaTypeVersion, + BasePinImpl_GetMediaType +}; + +static const BaseInputPinFuncTable tf_input_BaseInputFuncTable = { + TransformFilter_Input_Receive +}; + +static const BasePinFuncTable tf_output_BaseFuncTable = { + NULL, + BaseOutputPinImpl_AttemptConnection, + BasePinImpl_GetMediaTypeVersion, + TransformFilter_Output_GetMediaType +}; + +static const BaseOutputPinFuncTable tf_output_BaseOutputFuncTable = { + TransformFilter_Output_DecideBufferSize, + BaseOutputPinImpl_DecideAllocator, + BaseOutputPinImpl_BreakConnect +}; + +static HRESULT TransformFilter_Init(const IBaseFilterVtbl *pVtbl, const CLSID* pClsid, const TransformFilterFuncTable* pFuncsTable, TransformFilter* pTransformFilter) +{ + HRESULT hr; + PIN_INFO piInput; + PIN_INFO piOutput; + + BaseFilter_Init(&pTransformFilter->filter, pVtbl, pClsid, (DWORD_PTR)(__FILE__ ": TransformFilter.csFilter"), &tfBaseFuncTable); + + InitializeCriticalSection(&pTransformFilter->csReceive); + pTransformFilter->csReceive.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__": TransformFilter.csReceive"); + + /* pTransformFilter is already allocated */ + pTransformFilter->pFuncsTable = pFuncsTable; + ZeroMemory(&pTransformFilter->pmt, sizeof(pTransformFilter->pmt)); + pTransformFilter->npins = 2; + + pTransformFilter->ppPins = CoTaskMemAlloc(2 * sizeof(IPin *)); + + /* construct input pin */ + piInput.dir = PINDIR_INPUT; + piInput.pFilter = &pTransformFilter->filter.IBaseFilter_iface; + lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0])); + piOutput.dir = PINDIR_OUTPUT; + piOutput.pFilter = &pTransformFilter->filter.IBaseFilter_iface; + lstrcpynW(piOutput.achName, wcsOutputPinName, sizeof(piOutput.achName) / sizeof(piOutput.achName[0])); + + hr = BaseInputPin_Construct(&TransformFilter_InputPin_Vtbl, &piInput, &tf_input_BaseFuncTable, &tf_input_BaseInputFuncTable, &pTransformFilter->filter.csFilter, NULL, &pTransformFilter->ppPins[0]); + + if (SUCCEEDED(hr)) + { + hr = BaseOutputPin_Construct(&TransformFilter_OutputPin_Vtbl, sizeof(BaseOutputPin), &piOutput, &tf_output_BaseFuncTable, &tf_output_BaseOutputFuncTable, &pTransformFilter->filter.csFilter, &pTransformFilter->ppPins[1]); + + if (FAILED(hr)) + ERR("Cannot create output pin (%x)\n", hr); + else { + QualityControlImpl_Create( pTransformFilter->ppPins[0], &pTransformFilter->filter.IBaseFilter_iface, &pTransformFilter->qcimpl); + pTransformFilter->qcimpl->IQualityControl_iface.lpVtbl = &TransformFilter_QualityControl_Vtbl; + } + } + + if (SUCCEEDED(hr)) + { + ISeekingPassThru *passthru; + pTransformFilter->seekthru_unk = NULL; + hr = CoCreateInstance(&CLSID_SeekingPassThru, (IUnknown*)pTransformFilter, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&pTransformFilter->seekthru_unk); + if (SUCCEEDED(hr)) + { + IUnknown_QueryInterface(pTransformFilter->seekthru_unk, &IID_ISeekingPassThru, (void**)&passthru); + ISeekingPassThru_Init(passthru, FALSE, pTransformFilter->ppPins[0]); + ISeekingPassThru_Release(passthru); + } + } + + if (FAILED(hr)) + { + CoTaskMemFree(pTransformFilter->ppPins); + BaseFilterImpl_Release(&pTransformFilter->filter.IBaseFilter_iface); + } + + return hr; +} + +HRESULT TransformFilter_Construct(const IBaseFilterVtbl *pVtbl, LONG filter_size, const CLSID* pClsid, const TransformFilterFuncTable* pFuncsTable, IBaseFilter ** ppTransformFilter) +{ + TransformFilter* pTf; + + *ppTransformFilter = NULL; + + assert(filter_size >= sizeof(TransformFilter)); + + pTf = CoTaskMemAlloc(filter_size); + + if (!pTf) + return E_OUTOFMEMORY; + + ZeroMemory(pTf, filter_size); + + if (SUCCEEDED(TransformFilter_Init(pVtbl, pClsid, pFuncsTable, pTf))) + { + *ppTransformFilter = &pTf->filter.IBaseFilter_iface; + return S_OK; + } + + CoTaskMemFree(pTf); + return E_FAIL; +} + +HRESULT WINAPI TransformFilterImpl_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv) +{ + HRESULT hr; + TransformFilter *This = impl_from_IBaseFilter(iface); + TRACE("(%p/%p)->(%s, %p)\n", This, iface, debugstr_guid(riid), ppv); + + if (IsEqualIID(riid, &IID_IQualityControl)) { + *ppv = (IQualityControl*)This->qcimpl; + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; + } + else if (IsEqualIID(riid, &IID_IMediaSeeking) || + IsEqualIID(riid, &IID_IMediaPosition)) + { + return IUnknown_QueryInterface(This->seekthru_unk, riid, ppv); + } + hr = BaseFilterImpl_QueryInterface(iface, riid, ppv); + + if (FAILED(hr) && !IsEqualIID(riid, &IID_IPin) && !IsEqualIID(riid, &IID_IVideoWindow) && + !IsEqualIID(riid, &IID_IAMFilterMiscFlags)) + FIXME("No interface for %s!\n", debugstr_guid(riid)); + + return hr; +} + +ULONG WINAPI TransformFilterImpl_Release(IBaseFilter * iface) +{ + TransformFilter *This = impl_from_IBaseFilter(iface); + ULONG refCount = BaseFilterImpl_Release(iface); + + TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1); + + if (!refCount) + { + ULONG i; + + for (i = 0; i < This->npins; i++) + { + IPin *pConnectedTo; + + if (SUCCEEDED(IPin_ConnectedTo(This->ppPins[i], &pConnectedTo))) + { + IPin_Disconnect(pConnectedTo); + IPin_Release(pConnectedTo); + } + IPin_Disconnect(This->ppPins[i]); + + IPin_Release(This->ppPins[i]); + } + + CoTaskMemFree(This->ppPins); + + TRACE("Destroying transform filter\n"); + This->csReceive.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&This->csReceive); + FreeMediaType(&This->pmt); + QualityControlImpl_Destroy(This->qcimpl); + CoTaskMemFree(This); + IUnknown_Release(This->seekthru_unk); + + return 0; + } + else + return refCount; +} + +/** IMediaFilter methods **/ + +HRESULT WINAPI TransformFilterImpl_Stop(IBaseFilter * iface) +{ + TransformFilter *This = impl_from_IBaseFilter(iface); + HRESULT hr = S_OK; + + TRACE("(%p/%p)\n", This, iface); + + EnterCriticalSection(&This->csReceive); + { + This->filter.state = State_Stopped; + if (This->pFuncsTable->pfnStopStreaming) + hr = This->pFuncsTable->pfnStopStreaming(This); + } + LeaveCriticalSection(&This->csReceive); + + return hr; +} + +HRESULT WINAPI TransformFilterImpl_Pause(IBaseFilter * iface) +{ + TransformFilter *This = impl_from_IBaseFilter(iface); + HRESULT hr; + + TRACE("(%p/%p)->()\n", This, iface); + + EnterCriticalSection(&This->csReceive); + { + if (This->filter.state == State_Stopped) + hr = IBaseFilter_Run(iface, -1); + else + hr = S_OK; + + if (SUCCEEDED(hr)) + This->filter.state = State_Paused; + } + LeaveCriticalSection(&This->csReceive); + + return hr; +} + +HRESULT WINAPI TransformFilterImpl_Run(IBaseFilter * iface, REFERENCE_TIME tStart) +{ + HRESULT hr = S_OK; + TransformFilter *This = impl_from_IBaseFilter(iface); + + TRACE("(%p/%p)->(%s)\n", This, iface, wine_dbgstr_longlong(tStart)); + + EnterCriticalSection(&This->csReceive); + { + if (This->filter.state == State_Stopped) + { + impl_BaseInputPin_from_IPin(This->ppPins[0])->end_of_stream = 0; + if (This->pFuncsTable->pfnStartStreaming) + hr = This->pFuncsTable->pfnStartStreaming(This); + if (SUCCEEDED(hr)) + hr = BaseOutputPinImpl_Active(impl_BaseOutputPin_from_IPin(This->ppPins[1])); + } + + if (SUCCEEDED(hr)) + { + This->filter.rtStreamStart = tStart; + This->filter.state = State_Running; + } + } + LeaveCriticalSection(&This->csReceive); + + return hr; +} + +HRESULT WINAPI TransformFilterImpl_Notify(TransformFilter *iface, IBaseFilter *sender, Quality qm) +{ + return QualityControlImpl_Notify((IQualityControl*)iface->qcimpl, sender, qm); +} + +/** IBaseFilter implementation **/ + +HRESULT WINAPI TransformFilterImpl_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin) +{ + TransformFilter *This = impl_from_IBaseFilter(iface); + + TRACE("(%p/%p)->(%s,%p)\n", This, iface, debugstr_w(Id), ppPin); + + return E_NOTIMPL; +} + +static const IBaseFilterVtbl TransformFilter_Vtbl = +{ + TransformFilterImpl_QueryInterface, + BaseFilterImpl_AddRef, + TransformFilterImpl_Release, + BaseFilterImpl_GetClassID, + TransformFilterImpl_Stop, + TransformFilterImpl_Pause, + TransformFilterImpl_Run, + BaseFilterImpl_GetState, + BaseFilterImpl_SetSyncSource, + BaseFilterImpl_GetSyncSource, + BaseFilterImpl_EnumPins, + TransformFilterImpl_FindPin, + BaseFilterImpl_QueryFilterInfo, + BaseFilterImpl_JoinFilterGraph, + BaseFilterImpl_QueryVendorInfo +}; + +static HRESULT WINAPI TransformFilter_InputPin_EndOfStream(IPin * iface) +{ + BaseInputPin* This = impl_BaseInputPin_from_IPin(iface); + TransformFilter* pTransform; + IPin* ppin; + HRESULT hr; + + TRACE("(%p)->()\n", iface); + + /* Since we process samples synchronously, just forward notification downstream */ + pTransform = impl_from_IBaseFilter(This->pin.pinInfo.pFilter); + if (!pTransform) + hr = E_FAIL; + else + hr = IPin_ConnectedTo(pTransform->ppPins[1], &ppin); + if (SUCCEEDED(hr)) + { + hr = IPin_EndOfStream(ppin); + IPin_Release(ppin); + } + + if (FAILED(hr)) + ERR("%x\n", hr); + return hr; +} + +static HRESULT WINAPI TransformFilter_InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt) +{ + BaseInputPin* This = impl_BaseInputPin_from_IPin(iface); + TransformFilter* pTransform; + HRESULT hr = S_OK; + + TRACE("(%p)->(%p, %p)\n", iface, pReceivePin, pmt); + + pTransform = impl_from_IBaseFilter(This->pin.pinInfo.pFilter); + + if (pTransform->pFuncsTable->pfnSetMediaType) + hr = pTransform->pFuncsTable->pfnSetMediaType(pTransform, PINDIR_INPUT, pmt); + + if (SUCCEEDED(hr) && pTransform->pFuncsTable->pfnCompleteConnect) + hr = pTransform->pFuncsTable->pfnCompleteConnect(pTransform, PINDIR_INPUT, pReceivePin); + + if (SUCCEEDED(hr)) + { + hr = BaseInputPinImpl_ReceiveConnection(iface, pReceivePin, pmt); + if (FAILED(hr) && pTransform->pFuncsTable->pfnBreakConnect) + pTransform->pFuncsTable->pfnBreakConnect(pTransform, PINDIR_INPUT); + } + + return hr; +} + +static HRESULT WINAPI TransformFilter_InputPin_Disconnect(IPin * iface) +{ + BaseInputPin* This = impl_BaseInputPin_from_IPin(iface); + TransformFilter* pTransform; + + TRACE("(%p)->()\n", iface); + + pTransform = impl_from_IBaseFilter(This->pin.pinInfo.pFilter); + if (pTransform->pFuncsTable->pfnBreakConnect) + pTransform->pFuncsTable->pfnBreakConnect(pTransform, PINDIR_INPUT); + + return BasePinImpl_Disconnect(iface); +} + +static HRESULT WINAPI TransformFilter_InputPin_BeginFlush(IPin * iface) +{ + BaseInputPin* This = impl_BaseInputPin_from_IPin(iface); + TransformFilter* pTransform; + HRESULT hr = S_OK; + + TRACE("(%p)->()\n", iface); + + pTransform = impl_from_IBaseFilter(This->pin.pinInfo.pFilter); + EnterCriticalSection(&pTransform->filter.csFilter); + if (pTransform->pFuncsTable->pfnBeginFlush) + hr = pTransform->pFuncsTable->pfnBeginFlush(pTransform); + if (SUCCEEDED(hr)) + hr = BaseInputPinImpl_BeginFlush(iface); + LeaveCriticalSection(&pTransform->filter.csFilter); + return hr; +} + +static HRESULT WINAPI TransformFilter_InputPin_EndFlush(IPin * iface) +{ + BaseInputPin* This = impl_BaseInputPin_from_IPin(iface); + TransformFilter* pTransform; + HRESULT hr = S_OK; + + TRACE("(%p)->()\n", iface); + + pTransform = impl_from_IBaseFilter(This->pin.pinInfo.pFilter); + EnterCriticalSection(&pTransform->filter.csFilter); + if (pTransform->pFuncsTable->pfnEndFlush) + hr = pTransform->pFuncsTable->pfnEndFlush(pTransform); + if (SUCCEEDED(hr)) + hr = BaseInputPinImpl_EndFlush(iface); + LeaveCriticalSection(&pTransform->filter.csFilter); + return hr; +} + +static HRESULT WINAPI TransformFilter_InputPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) +{ + BaseInputPin* This = impl_BaseInputPin_from_IPin(iface); + TransformFilter* pTransform; + HRESULT hr = S_OK; + + TRACE("(%p)->()\n", iface); + + pTransform = impl_from_IBaseFilter(This->pin.pinInfo.pFilter); + EnterCriticalSection(&pTransform->filter.csFilter); + if (pTransform->pFuncsTable->pfnNewSegment) + hr = pTransform->pFuncsTable->pfnNewSegment(pTransform, tStart, tStop, dRate); + if (SUCCEEDED(hr)) + hr = BaseInputPinImpl_NewSegment(iface, tStart, tStop, dRate); + LeaveCriticalSection(&pTransform->filter.csFilter); + return hr; +} + +static const IPinVtbl TransformFilter_InputPin_Vtbl = +{ + BaseInputPinImpl_QueryInterface, + BasePinImpl_AddRef, + BaseInputPinImpl_Release, + BaseInputPinImpl_Connect, + TransformFilter_InputPin_ReceiveConnection, + TransformFilter_InputPin_Disconnect, + BasePinImpl_ConnectedTo, + BasePinImpl_ConnectionMediaType, + BasePinImpl_QueryPinInfo, + BasePinImpl_QueryDirection, + BasePinImpl_QueryId, + BaseInputPinImpl_QueryAccept, + BasePinImpl_EnumMediaTypes, + BasePinImpl_QueryInternalConnections, + TransformFilter_InputPin_EndOfStream, + TransformFilter_InputPin_BeginFlush, + TransformFilter_InputPin_EndFlush, + TransformFilter_InputPin_NewSegment +}; + +static const IPinVtbl TransformFilter_OutputPin_Vtbl = +{ + BaseOutputPinImpl_QueryInterface, + BasePinImpl_AddRef, + BaseOutputPinImpl_Release, + BaseOutputPinImpl_Connect, + BaseOutputPinImpl_ReceiveConnection, + BaseOutputPinImpl_Disconnect, + BasePinImpl_ConnectedTo, + BasePinImpl_ConnectionMediaType, + BasePinImpl_QueryPinInfo, + BasePinImpl_QueryDirection, + BasePinImpl_QueryId, + TransformFilter_Output_QueryAccept, + BasePinImpl_EnumMediaTypes, + BasePinImpl_QueryInternalConnections, + BaseOutputPinImpl_EndOfStream, + BaseOutputPinImpl_BeginFlush, + BaseOutputPinImpl_EndFlush, + BasePinImpl_NewSegment +}; + +static HRESULT WINAPI TransformFilter_QualityControlImpl_Notify(IQualityControl *iface, IBaseFilter *sender, Quality qm) { + QualityControlImpl *qc = (QualityControlImpl*)iface; + TransformFilter *This = impl_from_IBaseFilter(qc->self); + + if (This->pFuncsTable->pfnNotify) + return This->pFuncsTable->pfnNotify(This, sender, qm); + else + return TransformFilterImpl_Notify(This, sender, qm); +} + +static const IQualityControlVtbl TransformFilter_QualityControl_Vtbl = { + QualityControlImpl_QueryInterface, + QualityControlImpl_AddRef, + QualityControlImpl_Release, + TransformFilter_QualityControlImpl_Notify, + QualityControlImpl_SetSink +}; diff --git a/reactos/lib/3rdparty/strmbase/video.c b/reactos/lib/3rdparty/strmbase/video.c new file mode 100644 index 00000000000..1c4f3606f67 --- /dev/null +++ b/reactos/lib/3rdparty/strmbase/video.c @@ -0,0 +1,488 @@ +/* + * Generic Implementation of strmbase video classes + * + * Copyright 2012 Aric Stewart, CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include +#include "dshow.h" +#include "uuids.h" +#include "vfwmsgs.h" +#include "wine/debug.h" +#include "wine/unicode.h" +#include "wine/strmbase.h" + +WINE_DEFAULT_DEBUG_CHANNEL(strmbase); + +static inline BaseControlVideo *impl_from_IBasicVideo(IBasicVideo *iface) +{ + return CONTAINING_RECORD(iface, BaseControlVideo, IBasicVideo_iface); +} + +HRESULT WINAPI BaseControlVideo_Init(BaseControlVideo *pControlVideo, const IBasicVideoVtbl *lpVtbl, BaseFilter *owner, CRITICAL_SECTION *lock, BasePin* pPin, const BaseControlVideoFuncTable* pFuncsTable) +{ + pControlVideo->IBasicVideo_iface.lpVtbl = lpVtbl; + pControlVideo->pFilter = owner; + pControlVideo->pInterfaceLock = lock; + pControlVideo->pPin = pPin; + pControlVideo->pFuncsTable = pFuncsTable; + + BaseDispatch_Init(&pControlVideo->baseDispatch, &IID_IBasicVideo); + + return S_OK; +} + +HRESULT WINAPI BaseControlVideo_Destroy(BaseControlVideo *pControlVideo) +{ + return BaseDispatch_Destroy(&pControlVideo->baseDispatch); +} + +HRESULT WINAPI BaseControlVideoImpl_GetTypeInfoCount(IBasicVideo *iface, UINT *pctinfo) +{ + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + return BaseDispatchImpl_GetTypeInfoCount(&This->baseDispatch, pctinfo); +} + +HRESULT WINAPI BaseControlVideoImpl_GetTypeInfo(IBasicVideo *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) +{ + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + return BaseDispatchImpl_GetTypeInfo(&This->baseDispatch, &IID_NULL, iTInfo, lcid, ppTInfo); +} + +HRESULT WINAPI BaseControlVideoImpl_GetIDsOfNames(IBasicVideo *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) +{ + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + return BaseDispatchImpl_GetIDsOfNames(&This->baseDispatch, riid, rgszNames, cNames, lcid, rgDispId); +} + +HRESULT WINAPI BaseControlVideoImpl_Invoke(IBasicVideo *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo, UINT *puArgErr) +{ + BaseControlVideo *This = impl_from_IBasicVideo(iface); + HRESULT hr = S_OK; + ITypeInfo *pTypeInfo; + + hr = BaseDispatchImpl_GetTypeInfo(&This->baseDispatch, riid, 1, lcid, &pTypeInfo); + if (SUCCEEDED(hr)) + { + hr = ITypeInfo_Invoke(pTypeInfo, &This->IBasicVideo_iface, dispIdMember, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr); + ITypeInfo_Release(pTypeInfo); + } + + return hr; +} + +HRESULT WINAPI BaseControlVideoImpl_get_AvgTimePerFrame(IBasicVideo *iface, REFTIME *pAvgTimePerFrame) +{ + VIDEOINFOHEADER *vih; + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + if (!This->pPin->pConnectedTo) + return VFW_E_NOT_CONNECTED; + + TRACE("(%p/%p)->(%p)\n", This, iface, pAvgTimePerFrame); + + vih = This->pFuncsTable->pfnGetVideoFormat(This); + *pAvgTimePerFrame = vih->AvgTimePerFrame; + return S_OK; +} + +HRESULT WINAPI BaseControlVideoImpl_get_BitRate(IBasicVideo *iface, LONG *pBitRate) +{ + VIDEOINFOHEADER *vih; + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, pBitRate); + + if (!This->pPin->pConnectedTo) + return VFW_E_NOT_CONNECTED; + + vih = This->pFuncsTable->pfnGetVideoFormat(This); + *pBitRate = vih->dwBitRate; + return S_OK; +} + +HRESULT WINAPI BaseControlVideoImpl_get_BitErrorRate(IBasicVideo *iface, LONG *pBitErrorRate) +{ + VIDEOINFOHEADER *vih; + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, pBitErrorRate); + + if (!This->pPin->pConnectedTo) + return VFW_E_NOT_CONNECTED; + + vih = This->pFuncsTable->pfnGetVideoFormat(This); + *pBitErrorRate = vih->dwBitErrorRate; + return S_OK; +} + +HRESULT WINAPI BaseControlVideoImpl_get_VideoWidth(IBasicVideo *iface, LONG *pVideoWidth) +{ + VIDEOINFOHEADER *vih; + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, pVideoWidth); + + vih = This->pFuncsTable->pfnGetVideoFormat(This); + *pVideoWidth = vih->bmiHeader.biWidth; + + return S_OK; +} + +HRESULT WINAPI BaseControlVideoImpl_get_VideoHeight(IBasicVideo *iface, LONG *pVideoHeight) +{ + VIDEOINFOHEADER *vih; + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, pVideoHeight); + + vih = This->pFuncsTable->pfnGetVideoFormat(This); + *pVideoHeight = abs(vih->bmiHeader.biHeight); + + return S_OK; +} + +HRESULT WINAPI BaseControlVideoImpl_put_SourceLeft(IBasicVideo *iface, LONG SourceLeft) +{ + RECT SourceRect; + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%d)\n", This, iface, SourceLeft); + This->pFuncsTable->pfnGetSourceRect(This, &SourceRect); + SourceRect.left = SourceLeft; + This->pFuncsTable->pfnSetSourceRect(This, &SourceRect); + + return S_OK; +} + +HRESULT WINAPI BaseControlVideoImpl_get_SourceLeft(IBasicVideo *iface, LONG *pSourceLeft) +{ + RECT SourceRect; + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, pSourceLeft); + This->pFuncsTable->pfnGetSourceRect(This, &SourceRect); + *pSourceLeft = SourceRect.left; + + return S_OK; +} + +HRESULT WINAPI BaseControlVideoImpl_put_SourceWidth(IBasicVideo *iface, LONG SourceWidth) +{ + RECT SourceRect; + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%d)\n", This, iface, SourceWidth); + This->pFuncsTable->pfnGetSourceRect(This, &SourceRect); + SourceRect.right = SourceRect.left + SourceWidth; + This->pFuncsTable->pfnSetSourceRect(This, &SourceRect); + + return S_OK; +} + +HRESULT WINAPI BaseControlVideoImpl_get_SourceWidth(IBasicVideo *iface, LONG *pSourceWidth) +{ + RECT SourceRect; + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, pSourceWidth); + This->pFuncsTable->pfnGetSourceRect(This, &SourceRect); + *pSourceWidth = SourceRect.right - SourceRect.left; + + return S_OK; +} + +HRESULT WINAPI BaseControlVideoImpl_put_SourceTop(IBasicVideo *iface, LONG SourceTop) +{ + RECT SourceRect; + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%d)\n", This, iface, SourceTop); + This->pFuncsTable->pfnGetSourceRect(This, &SourceRect); + SourceRect.top = SourceTop; + This->pFuncsTable->pfnSetSourceRect(This, &SourceRect); + + return S_OK; +} + +HRESULT WINAPI BaseControlVideoImpl_get_SourceTop(IBasicVideo *iface, LONG *pSourceTop) +{ + RECT SourceRect; + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, pSourceTop); + This->pFuncsTable->pfnGetSourceRect(This, &SourceRect); + *pSourceTop = SourceRect.top; + + return S_OK; +} + +HRESULT WINAPI BaseControlVideoImpl_put_SourceHeight(IBasicVideo *iface, LONG SourceHeight) +{ + RECT SourceRect; + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%d)\n", This, iface, SourceHeight); + This->pFuncsTable->pfnGetSourceRect(This, &SourceRect); + SourceRect.bottom = SourceRect.top + SourceHeight; + This->pFuncsTable->pfnSetSourceRect(This, &SourceRect); + + return S_OK; +} + +HRESULT WINAPI BaseControlVideoImpl_get_SourceHeight(IBasicVideo *iface, LONG *pSourceHeight) +{ + RECT SourceRect; + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, pSourceHeight); + This->pFuncsTable->pfnGetSourceRect(This, &SourceRect); + + *pSourceHeight = SourceRect.bottom - SourceRect.top; + + return S_OK; +} + +HRESULT WINAPI BaseControlVideoImpl_put_DestinationLeft(IBasicVideo *iface, LONG DestinationLeft) +{ + RECT DestRect; + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%d)\n", This, iface, DestinationLeft); + This->pFuncsTable->pfnGetTargetRect(This, &DestRect); + DestRect.left = DestinationLeft; + This->pFuncsTable->pfnSetTargetRect(This, &DestRect); + + return S_OK; +} + +HRESULT WINAPI BaseControlVideoImpl_get_DestinationLeft(IBasicVideo *iface, LONG *pDestinationLeft) +{ + RECT DestRect; + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationLeft); + This->pFuncsTable->pfnGetTargetRect(This, &DestRect); + *pDestinationLeft = DestRect.left; + + return S_OK; +} + +HRESULT WINAPI BaseControlVideoImpl_put_DestinationWidth(IBasicVideo *iface, LONG DestinationWidth) +{ + RECT DestRect; + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%d)\n", This, iface, DestinationWidth); + This->pFuncsTable->pfnGetTargetRect(This, &DestRect); + DestRect.right = DestRect.left + DestinationWidth; + This->pFuncsTable->pfnSetTargetRect(This, &DestRect); + + return S_OK; +} + +HRESULT WINAPI BaseControlVideoImpl_get_DestinationWidth(IBasicVideo *iface, LONG *pDestinationWidth) +{ + RECT DestRect; + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationWidth); + This->pFuncsTable->pfnGetTargetRect(This, &DestRect); + *pDestinationWidth = DestRect.right - DestRect.left; + + return S_OK; +} + +HRESULT WINAPI BaseControlVideoImpl_put_DestinationTop(IBasicVideo *iface, LONG DestinationTop) +{ + RECT DestRect; + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%d)\n", This, iface, DestinationTop); + This->pFuncsTable->pfnGetTargetRect(This, &DestRect); + DestRect.top = DestinationTop; + This->pFuncsTable->pfnSetTargetRect(This, &DestRect); + + return S_OK; +} + +HRESULT WINAPI BaseControlVideoImpl_get_DestinationTop(IBasicVideo *iface, LONG *pDestinationTop) +{ + RECT DestRect; + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationTop); + This->pFuncsTable->pfnGetTargetRect(This, &DestRect); + *pDestinationTop = DestRect.top; + + return S_OK; +} + +HRESULT WINAPI BaseControlVideoImpl_put_DestinationHeight(IBasicVideo *iface, LONG DestinationHeight) +{ + RECT DestRect; + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%d)\n", This, iface, DestinationHeight); + This->pFuncsTable->pfnGetTargetRect(This, &DestRect); + DestRect.right = DestRect.left + DestinationHeight; + This->pFuncsTable->pfnSetTargetRect(This, &DestRect); + + return S_OK; +} + +HRESULT WINAPI BaseControlVideoImpl_get_DestinationHeight(IBasicVideo *iface, LONG *pDestinationHeight) +{ + RECT DestRect; + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationHeight); + This->pFuncsTable->pfnGetTargetRect(This, &DestRect); + *pDestinationHeight = DestRect.right - DestRect.left; + + return S_OK; +} + +HRESULT WINAPI BaseControlVideoImpl_SetSourcePosition(IBasicVideo *iface, LONG Left, LONG Top, LONG Width, LONG Height) +{ + RECT SourceRect; + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height); + SourceRect.left = Left; + SourceRect.top = Top; + SourceRect.right = Left + Width; + SourceRect.bottom = Top + Height; + This->pFuncsTable->pfnSetSourceRect(This, &SourceRect); + + return S_OK; +} + +HRESULT WINAPI BaseControlVideoImpl_GetSourcePosition(IBasicVideo *iface, LONG *pLeft, LONG *pTop, LONG *pWidth, LONG *pHeight) +{ + RECT SourceRect; + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight); + This->pFuncsTable->pfnGetSourceRect(This, &SourceRect); + + *pLeft = SourceRect.left; + *pTop = SourceRect.top; + *pWidth = SourceRect.right - SourceRect.left; + *pHeight = SourceRect.bottom - SourceRect.top; + + return S_OK; +} + +HRESULT WINAPI BaseControlVideoImpl_SetDefaultSourcePosition(IBasicVideo *iface) +{ + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->()\n", This, iface); + return This->pFuncsTable->pfnSetDefaultSourceRect(This); +} + +HRESULT WINAPI BaseControlVideoImpl_SetDestinationPosition(IBasicVideo *iface, LONG Left, LONG Top, LONG Width, LONG Height) +{ + RECT DestRect; + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height); + + DestRect.left = Left; + DestRect.top = Top; + DestRect.right = Left + Width; + DestRect.bottom = Top + Height; + This->pFuncsTable->pfnSetTargetRect(This, &DestRect); + + return S_OK; +} + +HRESULT WINAPI BaseControlVideoImpl_GetDestinationPosition(IBasicVideo *iface, LONG *pLeft, LONG *pTop, LONG *pWidth, LONG *pHeight) +{ + RECT DestRect; + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight); + This->pFuncsTable->pfnGetTargetRect(This, &DestRect); + + *pLeft = DestRect.left; + *pTop = DestRect.top; + *pWidth = DestRect.right - DestRect.left; + *pHeight = DestRect.bottom - DestRect.top; + + return S_OK; +} + +HRESULT WINAPI BaseControlVideoImpl_SetDefaultDestinationPosition(IBasicVideo *iface) +{ + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->()\n", This, iface); + return This->pFuncsTable->pfnSetDefaultTargetRect(This); +} + +HRESULT WINAPI BaseControlVideoImpl_GetVideoSize(IBasicVideo *iface, LONG *pWidth, LONG *pHeight) +{ + VIDEOINFOHEADER *vih; + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight); + + vih = This->pFuncsTable->pfnGetVideoFormat(This); + *pHeight = vih->bmiHeader.biHeight; + *pWidth = vih->bmiHeader.biWidth; + + return S_OK; +} + +HRESULT WINAPI BaseControlVideoImpl_GetVideoPaletteEntries(IBasicVideo *iface, LONG StartIndex, LONG Entries, LONG *pRetrieved, LONG *pPalette) +{ + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + TRACE("(%p/%p)->(%d, %d, %p, %p)\n", This, iface, StartIndex, Entries, pRetrieved, pPalette); + + if (pRetrieved) + *pRetrieved = 0; + return VFW_E_NO_PALETTE_AVAILABLE; +} + +HRESULT WINAPI BaseControlVideoImpl_GetCurrentImage(IBasicVideo *iface, LONG *pBufferSize, LONG *pDIBImage) +{ + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + return This->pFuncsTable->pfnGetStaticImage(This, pBufferSize, pDIBImage); +} + +HRESULT WINAPI BaseControlVideoImpl_IsUsingDefaultSource(IBasicVideo *iface) +{ + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + return This->pFuncsTable->pfnIsDefaultSourceRect(This); +} + +HRESULT WINAPI BaseControlVideoImpl_IsUsingDefaultDestination(IBasicVideo *iface) +{ + BaseControlVideo *This = impl_from_IBasicVideo(iface); + + return This->pFuncsTable->pfnIsDefaultTargetRect(This); +} diff --git a/reactos/lib/3rdparty/strmbase/window.c b/reactos/lib/3rdparty/strmbase/window.c new file mode 100644 index 00000000000..cb448e347b1 --- /dev/null +++ b/reactos/lib/3rdparty/strmbase/window.c @@ -0,0 +1,738 @@ +/* + * Generic Implementation of strmbase window classes + * + * Copyright 2012 Aric Stewart, CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include "dshow.h" +#include "wine/debug.h" +#include "wine/unicode.h" +#include "wine/strmbase.h" +#include "uuids.h" +#include "vfwmsgs.h" +#include + +WINE_DEFAULT_DEBUG_CHANNEL(strmbase); + +static inline BaseControlWindow *impl_from_IVideoWindow( IVideoWindow *iface) +{ + return CONTAINING_RECORD(iface, BaseControlWindow, IVideoWindow_iface); +} + +static inline BaseControlWindow *impl_from_BaseWindow(BaseWindow *iface) +{ + return CONTAINING_RECORD(iface, BaseControlWindow, baseWindow); +} + +static LRESULT CALLBACK WndProcW(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + BaseWindow* This = (BaseWindow*)GetWindowLongPtrW(hwnd, 0); + + if (!This) + return DefWindowProcW(hwnd, uMsg, wParam, lParam); + + if (This->pFuncsTable->pfnOnReceiveMessage) + return This->pFuncsTable->pfnOnReceiveMessage(This, hwnd, uMsg, wParam, lParam); + else + return BaseWindowImpl_OnReceiveMessage(This, hwnd, uMsg, wParam, lParam); +} + +LRESULT WINAPI BaseWindowImpl_OnReceiveMessage(BaseWindow *This, HWND hwnd, INT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (This->pFuncsTable->pfnPossiblyEatMessage && This->pFuncsTable->pfnPossiblyEatMessage(This, uMsg, wParam, lParam)) + return 0; + + switch (uMsg) + { + case WM_SIZE: + if (This->pFuncsTable->pfnOnSize) + return This->pFuncsTable->pfnOnSize(This, LOWORD(lParam), HIWORD(lParam)); + else + return BaseWindowImpl_OnSize(This, LOWORD(lParam), HIWORD(lParam)); + } + + return DefWindowProcW(hwnd, uMsg, wParam, lParam); +} + +BOOL WINAPI BaseWindowImpl_OnSize(BaseWindow *This, LONG Width, LONG Height) +{ + This->Width = Width; + This->Height = Height; + return TRUE; +} + +HRESULT WINAPI BaseWindow_Init(BaseWindow *pBaseWindow, const BaseWindowFuncTable* pFuncsTable) +{ + if (!pFuncsTable) + return E_INVALIDARG; + + ZeroMemory(pBaseWindow,sizeof(BaseWindow)); + pBaseWindow->pFuncsTable = pFuncsTable; + + return S_OK; +} + +HRESULT WINAPI BaseWindow_Destroy(BaseWindow *This) +{ + if (This->hWnd) + BaseWindowImpl_DoneWithWindow(This); + + HeapFree(GetProcessHeap(), 0, This); + return S_OK; +} + +HRESULT WINAPI BaseWindowImpl_PrepareWindow(BaseWindow *This) +{ + WNDCLASSW winclass; + static const WCHAR windownameW[] = { 'A','c','t','i','v','e','M','o','v','i','e',' ','W','i','n','d','o','w',0 }; + + This->pClassName = This->pFuncsTable->pfnGetClassWindowStyles(This, &This->ClassStyles, &This->WindowStyles, &This->WindowStylesEx); + + winclass.style = This->ClassStyles; + winclass.lpfnWndProc = WndProcW; + winclass.cbClsExtra = 0; + winclass.cbWndExtra = sizeof(BaseWindow*); + winclass.hInstance = This->hInstance; + winclass.hIcon = NULL; + winclass.hCursor = NULL; + winclass.hbrBackground = GetStockObject(BLACK_BRUSH); + winclass.lpszMenuName = NULL; + winclass.lpszClassName = This->pClassName; + if (!RegisterClassW(&winclass) && GetLastError() != ERROR_CLASS_ALREADY_EXISTS) + { + ERR("Unable to register window class: %u\n", GetLastError()); + return E_FAIL; + } + + This->hWnd = CreateWindowExW(This->WindowStylesEx, + This->pClassName, windownameW, + This->WindowStyles, + CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, NULL, NULL, This->hInstance, + NULL); + + if (!This->hWnd) + { + ERR("Unable to create window\n"); + return E_FAIL; + } + + SetWindowLongPtrW(This->hWnd, 0, (LONG_PTR)This); + + This->hDC = GetDC(This->hWnd); + + return S_OK; +} + +HRESULT WINAPI BaseWindowImpl_DoneWithWindow(BaseWindow *This) +{ + if (!This->hWnd) + return S_OK; + + if (This->hDC) + ReleaseDC(This->hWnd, This->hDC); + This->hDC = NULL; + + DestroyWindow(This->hWnd); + This->hWnd = NULL; + + return S_OK; +} + +RECT WINAPI BaseWindowImpl_GetDefaultRect(BaseWindow *This) +{ + static RECT defRect = {0, 0, 800, 600}; + return defRect; +} + +BOOL WINAPI BaseControlWindowImpl_PossiblyEatMessage(BaseWindow *This, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + BaseControlWindow* pControlWindow = impl_from_BaseWindow(This); + + if (pControlWindow->hwndDrain) + { + switch(uMsg) + { + case WM_KEYDOWN: + case WM_KEYUP: + case WM_LBUTTONDBLCLK: + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MBUTTONDBLCLK: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_MOUSEACTIVATE: + case WM_MOUSEMOVE: + case WM_NCLBUTTONDBLCLK: + case WM_NCLBUTTONDOWN: + case WM_NCLBUTTONUP: + case WM_NCMBUTTONDBLCLK: + case WM_NCMBUTTONDOWN: + case WM_NCMBUTTONUP: + case WM_NCMOUSEMOVE: + case WM_NCRBUTTONDBLCLK: + case WM_NCRBUTTONDOWN: + case WM_NCRBUTTONUP: + case WM_RBUTTONDBLCLK: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + PostMessageW(pControlWindow->hwndDrain, uMsg, wParam, lParam); + return TRUE; + default: + break; + } + } + return FALSE; +} + +HRESULT WINAPI BaseControlWindow_Init(BaseControlWindow *pControlWindow, const IVideoWindowVtbl *lpVtbl, BaseFilter *owner, CRITICAL_SECTION *lock, BasePin* pPin,const BaseWindowFuncTable *pFuncsTable) +{ + HRESULT hr; + + hr = BaseWindow_Init(&pControlWindow->baseWindow, pFuncsTable); + if (SUCCEEDED(hr)) + { + BaseDispatch_Init(&pControlWindow->baseDispatch, &IID_IVideoWindow); + pControlWindow->IVideoWindow_iface.lpVtbl = lpVtbl; + pControlWindow->AutoShow = TRUE; + pControlWindow->hwndDrain = NULL; + pControlWindow->hwndOwner = NULL; + pControlWindow->pFilter = owner; + pControlWindow->pInterfaceLock = lock; + pControlWindow->pPin = pPin; + } + return hr; +} + +HRESULT WINAPI BaseControlWindow_Destroy(BaseControlWindow *pControlWindow) +{ + BaseWindowImpl_DoneWithWindow(&pControlWindow->baseWindow); + return BaseDispatch_Destroy(&pControlWindow->baseDispatch); +} + +HRESULT WINAPI BaseControlWindowImpl_GetTypeInfoCount(IVideoWindow *iface, UINT *pctinfo) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + return BaseDispatchImpl_GetTypeInfoCount(&This->baseDispatch, pctinfo); +} + +HRESULT WINAPI BaseControlWindowImpl_GetTypeInfo(IVideoWindow *iface, UINT iTInfo, LCID lcid, ITypeInfo**ppTInfo) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + return BaseDispatchImpl_GetTypeInfo(&This->baseDispatch, &IID_NULL, iTInfo, lcid, ppTInfo); +} + +HRESULT WINAPI BaseControlWindowImpl_GetIDsOfNames(IVideoWindow *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) + { + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + return BaseDispatchImpl_GetIDsOfNames(&This->baseDispatch, riid, rgszNames, cNames, lcid, rgDispId); +} + +HRESULT WINAPI BaseControlWindowImpl_Invoke(IVideoWindow *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo, UINT *puArgErr) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + HRESULT hr = S_OK; + ITypeInfo *pTypeInfo; + + hr = BaseDispatchImpl_GetTypeInfo(&This->baseDispatch, riid, 1, lcid, &pTypeInfo); + if (SUCCEEDED(hr)) + { + hr = ITypeInfo_Invoke(pTypeInfo, &This->IVideoWindow_iface, dispIdMember, wFlags, pDispParams, pVarResult, pExepInfo, puArgErr); + ITypeInfo_Release(pTypeInfo); + } + + return hr; +} + +HRESULT WINAPI BaseControlWindowImpl_put_Caption(IVideoWindow *iface, BSTR strCaption) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + TRACE("(%p/%p)->(%s (%p))\n", This, iface, debugstr_w(strCaption), strCaption); + + if (!SetWindowTextW(This->baseWindow.hWnd, strCaption)) + return E_FAIL; + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_get_Caption(IVideoWindow *iface, BSTR *strCaption) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, strCaption); + + GetWindowTextW(This->baseWindow.hWnd, (LPWSTR)strCaption, 100); + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_put_WindowStyle(IVideoWindow *iface, LONG WindowStyle) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + LONG old; + + old = GetWindowLongW(This->baseWindow.hWnd, GWL_STYLE); + + TRACE("(%p/%p)->(%x -> %x)\n", This, iface, old, WindowStyle); + + if (WindowStyle & (WS_DISABLED|WS_HSCROLL|WS_ICONIC|WS_MAXIMIZE|WS_MINIMIZE|WS_VSCROLL)) + return E_INVALIDARG; + + SetWindowLongW(This->baseWindow.hWnd, GWL_STYLE, WindowStyle); + SetWindowPos(This->baseWindow.hWnd,0,0,0,0,0,SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOZORDER); + This->baseWindow.WindowStyles = WindowStyle; + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_get_WindowStyle(IVideoWindow *iface, LONG *WindowStyle) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyle); + + *WindowStyle = This->baseWindow.WindowStyles; + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_put_WindowStyleEx(IVideoWindow *iface, LONG WindowStyleEx) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + TRACE("(%p/%p)->(%d)\n", This, iface, WindowStyleEx); + + if (!SetWindowLongW(This->baseWindow.hWnd, GWL_EXSTYLE, WindowStyleEx)) + return E_FAIL; + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_get_WindowStyleEx(IVideoWindow *iface, LONG *WindowStyleEx) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, WindowStyleEx); + + *WindowStyleEx = GetWindowLongW(This->baseWindow.hWnd, GWL_EXSTYLE); + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_put_AutoShow(IVideoWindow *iface, LONG AutoShow) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + TRACE("(%p/%p)->(%d)\n", This, iface, AutoShow); + + This->AutoShow = AutoShow; + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_get_AutoShow(IVideoWindow *iface, LONG *AutoShow) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, AutoShow); + + *AutoShow = This->AutoShow; + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_put_WindowState(IVideoWindow *iface, LONG WindowState) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + TRACE("(%p/%p)->(%d)\n", This, iface, WindowState); + ShowWindow(This->baseWindow.hWnd, WindowState); + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_get_WindowState(IVideoWindow *iface, LONG *WindowState) +{ + WINDOWPLACEMENT place; + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + place.length = sizeof(place); + GetWindowPlacement(This->baseWindow.hWnd, &place); + TRACE("(%p/%p)->(%p)\n", This, iface, WindowState); + *WindowState = place.showCmd; + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_put_BackgroundPalette(IVideoWindow *iface, LONG BackgroundPalette) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + FIXME("(%p/%p)->(%d): stub !!!\n", This, iface, BackgroundPalette); + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_get_BackgroundPalette(IVideoWindow *iface, LONG *pBackgroundPalette) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, pBackgroundPalette); + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_put_Visible(IVideoWindow *iface, LONG Visible) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + TRACE("(%p/%p)->(%d)\n", This, iface, Visible); + + ShowWindow(This->baseWindow.hWnd, Visible ? SW_SHOW : SW_HIDE); + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_get_Visible(IVideoWindow *iface, LONG *pVisible) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, pVisible); + + *pVisible = IsWindowVisible(This->baseWindow.hWnd); + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_put_Left(IVideoWindow *iface, LONG Left) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + RECT WindowPos; + + TRACE("(%p/%p)->(%d)\n", This, iface, Left); + + GetWindowRect(This->baseWindow.hWnd, &WindowPos); + if (!SetWindowPos(This->baseWindow.hWnd, NULL, Left, WindowPos.top, 0, 0, SWP_NOZORDER|SWP_NOSIZE)) + return E_FAIL; + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_get_Left(IVideoWindow *iface, LONG *pLeft) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + RECT WindowPos; + + TRACE("(%p/%p)->(%p)\n", This, iface, pLeft); + GetWindowRect(This->baseWindow.hWnd, &WindowPos); + + *pLeft = WindowPos.left; + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_put_Width(IVideoWindow *iface, LONG Width) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + TRACE("(%p/%p)->(%d)\n", This, iface, Width); + + if (!SetWindowPos(This->baseWindow.hWnd, NULL, 0, 0, Width, This->baseWindow.Height, SWP_NOZORDER|SWP_NOMOVE)) + return E_FAIL; + + This->baseWindow.Width = Width; + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_get_Width(IVideoWindow *iface, LONG *pWidth) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, pWidth); + + *pWidth = This->baseWindow.Width; + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_put_Top(IVideoWindow *iface, LONG Top) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + RECT WindowPos; + + TRACE("(%p/%p)->(%d)\n", This, iface, Top); + GetWindowRect(This->baseWindow.hWnd, &WindowPos); + + if (!SetWindowPos(This->baseWindow.hWnd, NULL, WindowPos.left, Top, 0, 0, SWP_NOZORDER|SWP_NOSIZE)) + return E_FAIL; + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_get_Top(IVideoWindow *iface, LONG *pTop) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + RECT WindowPos; + + TRACE("(%p/%p)->(%p)\n", This, iface, pTop); + GetWindowRect(This->baseWindow.hWnd, &WindowPos); + + *pTop = WindowPos.top; + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_put_Height(IVideoWindow *iface, LONG Height) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + TRACE("(%p/%p)->(%d)\n", This, iface, Height); + + if (!SetWindowPos(This->baseWindow.hWnd, NULL, 0, 0, This->baseWindow.Width, Height, SWP_NOZORDER|SWP_NOMOVE)) + return E_FAIL; + + This->baseWindow.Height = Height; + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_get_Height(IVideoWindow *iface, LONG *pHeight) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, pHeight); + + *pHeight = This->baseWindow.Height; + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_put_Owner(IVideoWindow *iface, OAHWND Owner) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Owner); + + This->hwndOwner = (HWND)Owner; + SetParent(This->baseWindow.hWnd, This->hwndOwner); + if (This->baseWindow.WindowStyles & WS_CHILD) + { + LONG old = GetWindowLongW(This->baseWindow.hWnd, GWL_STYLE); + if (old != This->baseWindow.WindowStyles) + { + SetWindowLongW(This->baseWindow.hWnd, GWL_STYLE, This->baseWindow.WindowStyles); + SetWindowPos(This->baseWindow.hWnd,0,0,0,0,0,SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOZORDER); + } + } + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_get_Owner(IVideoWindow *iface, OAHWND *Owner) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, Owner); + + *(HWND*)Owner = This->hwndOwner; + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_put_MessageDrain(IVideoWindow *iface, OAHWND Drain) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + TRACE("(%p/%p)->(%08x)\n", This, iface, (DWORD) Drain); + + This->hwndDrain = (HWND)Drain; + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_get_MessageDrain(IVideoWindow *iface, OAHWND *Drain) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + TRACE("(%p/%p)->(%p)\n", This, iface, Drain); + + *Drain = (OAHWND)This->hwndDrain; + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_get_BorderColor(IVideoWindow *iface, LONG *Color) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, Color); + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_put_BorderColor(IVideoWindow *iface, LONG Color) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + FIXME("(%p/%p)->(%d): stub !!!\n", This, iface, Color); + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_get_FullScreenMode(IVideoWindow *iface, LONG *FullScreenMode) +{ + TRACE("(%p)->(%p)\n", iface, FullScreenMode); + + return E_NOTIMPL; +} + +HRESULT WINAPI BaseControlWindowImpl_put_FullScreenMode(IVideoWindow *iface, LONG FullScreenMode) +{ + TRACE("(%p)->(%d)\n", iface, FullScreenMode); + return E_NOTIMPL; +} + +HRESULT WINAPI BaseControlWindowImpl_SetWindowForeground(IVideoWindow *iface, LONG Focus) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + BOOL ret; + IPin* pPin; + HRESULT hr; + + TRACE("(%p/%p)->(%d)\n", This, iface, Focus); + + if ((Focus != FALSE) && (Focus != TRUE)) + return E_INVALIDARG; + + hr = IPin_ConnectedTo(&This->pPin->IPin_iface, &pPin); + if ((hr != S_OK) || !pPin) + return VFW_E_NOT_CONNECTED; + + if (Focus) + ret = SetForegroundWindow(This->baseWindow.hWnd); + else + ret = SetWindowPos(This->baseWindow.hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); + + if (!ret) + return E_FAIL; + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_SetWindowPosition(IVideoWindow *iface, LONG Left, LONG Top, LONG Width, LONG Height) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + TRACE("(%p/%p)->(%d, %d, %d, %d)\n", This, iface, Left, Top, Width, Height); + + if (!SetWindowPos(This->baseWindow.hWnd, NULL, Left, Top, Width, Height, SWP_NOZORDER)) + return E_FAIL; + + This->baseWindow.Width = Width; + This->baseWindow.Height = Height; + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_GetWindowPosition(IVideoWindow *iface, LONG *pLeft, LONG *pTop, LONG *pWidth, LONG *pHeight) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + RECT WindowPos; + + TRACE("(%p/%p)->(%p, %p, %p, %p)\n", This, iface, pLeft, pTop, pWidth, pHeight); + GetWindowRect(This->baseWindow.hWnd, &WindowPos); + + *pLeft = WindowPos.left; + *pTop = WindowPos.top; + *pWidth = This->baseWindow.Width; + *pHeight = This->baseWindow.Height; + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_NotifyOwnerMessage(IVideoWindow *iface, OAHWND hwnd, LONG uMsg, LONG_PTR wParam, LONG_PTR lParam) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + TRACE("(%p/%p)->(%08lx, %d, %08lx, %08lx)\n", This, iface, hwnd, uMsg, wParam, lParam); + + if (!PostMessageW(This->baseWindow.hWnd, uMsg, wParam, lParam)) + return E_FAIL; + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_GetMinIdealImageSize(IVideoWindow *iface, LONG *pWidth, LONG *pHeight) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + RECT defaultRect; + + TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight); + defaultRect = This->baseWindow.pFuncsTable->pfnGetDefaultRect(&This->baseWindow); + + *pWidth = defaultRect.right - defaultRect.left; + *pHeight = defaultRect.bottom - defaultRect.top; + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_GetMaxIdealImageSize(IVideoWindow *iface, LONG *pWidth, LONG *pHeight) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + RECT defaultRect; + + TRACE("(%p/%p)->(%p, %p)\n", This, iface, pWidth, pHeight); + defaultRect = This->baseWindow.pFuncsTable->pfnGetDefaultRect(&This->baseWindow); + + *pWidth = defaultRect.right - defaultRect.left; + *pHeight = defaultRect.bottom - defaultRect.top; + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_GetRestorePosition(IVideoWindow *iface, LONG *pLeft, LONG *pTop, LONG *pWidth, LONG *pHeight) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + FIXME("(%p/%p)->(%p, %p, %p, %p): stub !!!\n", This, iface, pLeft, pTop, pWidth, pHeight); + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_HideCursor(IVideoWindow *iface, LONG HideCursor) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + FIXME("(%p/%p)->(%d): stub !!!\n", This, iface, HideCursor); + + return S_OK; +} + +HRESULT WINAPI BaseControlWindowImpl_IsCursorHidden(IVideoWindow *iface, LONG *CursorHidden) +{ + BaseControlWindow* This = impl_from_IVideoWindow(iface); + + FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, CursorHidden); + + return S_OK; +} diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index ad5f4da8829..3a35d92aeef 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -37,7 +37,7 @@ reactos/dll/directx/dsound # Synced to Wine-1.5.26 reactos/dll/directx/dxdiagn # Synced to Wine-0_9_5 reactos/dll/directx/msdmo # Autosync reactos/dll/directx/qedit # Autosync -reactos/dll/directx/quartz # Autosync +reactos/dll/directx/quartz # Synced to Wine-1.5.26 reactos/dll/win32/activeds # Synced to Wine-1.1.43? reactos/dll/win32/actxprxy # Synced to Wine-1.5.26 reactos/dll/win32/advpack # Synced to Wine-1.5.26 @@ -228,7 +228,8 @@ In addition the following libs, dlls and source files are mostly based on code p from Winehq CVS. If you are looking to update something in these files check Wine current souces first as it may already be fixed. -reactos/lib/sdk/uuid # Synced to Wine-1.1.42 +reactos/lib/3rdparty/strmbase # Synced to Wine-1.5.26 +reactos/lib/sdk/uuid # Synced to Wine-1.1.42 advapi32 - reactos/dll/win32/advapi32/crypt/*.c # Unknown