* Sync with Wine 1.5.26.
[STRMBASE]
* Import from Wine 1.5.26.
[DXSDK]
* Remove a redundant (and outdated) strmif.idl.
* Update axextend.idl.
[PSDK]
* Update control.idl and strmif.idl.
* Correct the OVERLAPPED structure.
[CMAKE]
* Look for inclusions in psdk before dxsdk.
[DEVENUM]
* Adapt to the axextend.idl update.
svn path=/trunk/; revision=59265
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
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;
DEVENUM_ReadPinTypes(hkeyPinKey, rgPin);
- ++rgf2->u.s.cPins;
+ ++rgf2->u.s1.cPins;
continue;
error_cleanup:
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)
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 ||
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);
}
}
}
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;
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
+ avidec.c
+ avisplit.c
dsoundrender.c
+ enumfilters.c
enummedia.c
- control.c
- avisplit.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)
//#include "wine/unicode.h"
#include <wine/debug.h>
-#include "transform.h"
-
WINE_DEFAULT_DEBUG_CHANNEL(quartz);
typedef struct ACMWrapperImpl
{
- TransformFilterImpl tf;
+ TransformFilter tf;
+
HACMSTREAM has;
LPWAVEFORMATEX pWfIn;
LPWAVEFORMATEX pWfOut;
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;
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 */
WARN("Discontinuity\n");
tMed = tStart;
+ mtMed = mtStart;
TRACE("Sample data ptr = %p, size = %d\n", pbSrcStream, cbSrcStream);
if (FAILED(hr))
{
ERR("Unable to retrieve media type\n");
- LeaveCriticalSection(&This->tf.csFilter);
+ LeaveCriticalSection(&This->tf.csReceive);
return hr;
}
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);
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);
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))
ash.pbSrc += ash.cbSrcLengthUsed;
ash.cbSrcLength -= ash.cbSrcLengthUsed;
- if (pOutSample)
- IMediaSample_Release(pOutSample);
+ IMediaSample_Release(pOutSample);
pOutSample = NULL;
}
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)) &&
(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;
{
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;
}
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_Receive,
NULL,
- ACMWrapper_ProcessSampleData,
NULL,
+ ACMWrapper_SetMediaType,
+ ACMWrapper_CompleteConnect,
+ ACMWrapper_BreakConnect,
NULL,
- ACMWrapper_ConnectInput,
- ACMWrapper_Cleanup
+ NULL,
+ NULL,
+ NULL
};
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;
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
+};
//#include <wine/unicode.h>
#include <wine/debug.h>
-#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 )
+{
+ 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 = (AVIDecImpl*)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)
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;
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))
{
/* 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;
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);
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)))
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;
}
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);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI AVIDec_BreakConnect(TransformFilter *tf, PIN_DIRECTION dir)
+{
+ 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;
+ 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 const TransformFuncsTable AVIDec_FuncsTable = {
- AVIDec_ProcessBegin,
- AVIDec_ProcessSampleData,
- AVIDec_ProcessEnd,
+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_SetMediaType,
+ AVIDec_CompleteConnect,
+ AVIDec_BreakConnect,
NULL,
- AVIDec_ConnectInput,
- AVIDec_Cleanup
+ NULL,
+ AVIDec_EndFlush,
+ NULL,
+ AVIDec_NotifyDrop
};
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
+};
*/
#include "quartz_private.h"
-#include "control_private.h"
#include "pin.h"
//#include "uuids.h"
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
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;
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
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 */
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
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);
}
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])
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);
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;
/* 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 */
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);
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)
{
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;
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;
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;
+++ /dev/null
-/*
- * 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 <wine/debug.h>
-
-#include <assert.h>
-
-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
-};
+++ /dev/null
-/*
- * 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*/
/*
- * 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
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-import "objidl.idl";
-
-#include <devenum.idl>
-
-#include <axcore.idl>
-
-#include <axextend.idl>
-
-#include <dyngraph.idl>
-
-/* TODO: #include <dvdif.h> */
-#include <vmrender.idl>
+#include "control.idl"
--- /dev/null
+HKCR
+{
+ NoRemove Typelib
+ {
+ NoRemove '{56A868B0-0AD4-11CE-B03A-0020AF0BA770}'
+ {
+ '1.0' = s 'QuartzTypeLib'
+ {
+ '0' { win32 = s '%MODULE%' }
+ FLAGS = s '0'
+ }
+ }
+ }
+ NoRemove Interface
+ {
+ }
+ NoRemove CLSID
+ {
+ }
+}
#include <config.h>
#include "quartz_private.h"
-#include "control_private.h"
#include "pin.h"
//#include "uuids.h"
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;
-
- LONG refCount;
- CRITICAL_SECTION csFilter;
- FILTER_STATE state;
- REFERENCE_TIME rtStreamStart, rtLastStop;
- IReferenceClock * pClock;
- FILTER_INFO filterInfo;
+ BaseRenderer renderer;
+ BasicAudio basicAudio;
- 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 S_OK;
+ return CONTAINING_RECORD(iface, DSoundRenderImpl, renderer);
}
-static HRESULT sound_mod_start(IBaseFilter *iface)
+static inline DSoundRenderImpl *impl_from_IBaseFilter(IBaseFilter *iface)
{
- TRACE("(%p)\n", iface);
-
- return S_OK;
+ return CONTAINING_RECORD(iface, DSoundRenderImpl, renderer.filter.IBaseFilter_iface);
}
-static HRESULT sound_mod_rate(IBaseFilter *iface)
+static inline DSoundRenderImpl *impl_from_IBasicAudio(IBasicAudio *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;
+ return CONTAINING_RECORD(iface, DSoundRenderImpl, basicAudio.IBasicAudio_iface);
+}
- if (freq < DSBFREQUENCY_MIN)
- return VFW_E_UNSUPPORTED_AUDIO;
+static inline DSoundRenderImpl *impl_from_IReferenceClock(IReferenceClock *iface)
+{
+ return CONTAINING_RECORD(iface, DSoundRenderImpl, IReferenceClock_iface);
+}
- return S_OK;
+static inline DSoundRenderImpl *impl_from_IAMDirectSound(IAMDirectSound *iface)
+{
+ return CONTAINING_RECORD(iface, DSoundRenderImpl, IAMDirectSound_iface);
}
-static inline HRESULT DSoundRender_GetPos(DSoundRenderImpl *This, DWORD *pPlayPos, REFERENCE_TIME *pRefTime)
+static inline DSoundRenderImpl *impl_from_IAMFilterMiscFlags(IAMFilterMiscFlags *iface)
{
- HRESULT hr;
+ return CONTAINING_RECORD(iface, DSoundRenderImpl, IAMFilterMiscFlags_iface);
+}
- EnterCriticalSection(&This->csFilter);
- {
- DWORD state;
- DWORD write_pos;
+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;
+}
- hr = IDirectSoundBuffer_GetStatus(This->dsbuffer, &state);
- if (SUCCEEDED(hr) && !(state & DSBSTATUS_PLAYING) && This->state == State_Running)
- {
- TRACE("Not playing, kickstarting the engine\n");
+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;
+}
- hr = IDirectSoundBuffer_Play(This->dsbuffer, 0, 0, DSBPLAY_LOOPING);
- if (FAILED(hr))
- ERR("Can't play sound buffer (%x)\n", hr);
+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;
+}
- 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;
+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 (pRefTime)
- {
- REFERENCE_TIME play_time;
- play_time = ((REFERENCE_TIME)This->play_loops*10000000) +
- ((REFERENCE_TIME)play_pos*10000000/This->buf_size);
+ 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;
+}
- /* Don't let time run backwards */
- if(play_time-This->play_time > 0)
- This->play_time = play_time;
- else
- hr = S_FALSE;
+static HRESULT DSoundRender_HandleEndOfStream(DSoundRenderImpl *This)
+{
+ while (1)
+ {
+ DWORD pos1, pos2;
+ DSoundRender_UpdatePositions(This, &pos1, &pos2);
+ if (pos1 == pos2)
+ break;
- *pRefTime = This->play_time;
- }
- }
+ 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;
}
- LeaveCriticalSection(&This->csFilter);
- return hr;
+ return S_OK;
}
-static HRESULT DSoundRender_SendSampleData(DSoundRenderImpl* This, const BYTE *data, DWORD size)
+static HRESULT DSoundRender_SendSampleData(DSoundRenderImpl* This, REFERENCE_TIME tStart, REFERENCE_TIME tStop, 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;
+ HRESULT hr;
- do {
+ while (size && This->renderer.filter.state != State_Stopped) {
+ DWORD writepos, skip = 0, free, size1, size2, ret;
+ BYTE *buf1, *buf2;
- 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;
-
- /* Wait for enough of the buffer to empty before filling it */
- if(buf_free < This->buf_size/4)
- {
- Sleep(50);
+ hr = S_FALSE;
+
+ 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;
+
+ if (skip)
+ FIXME("Sample dropped %u of %u bytes\n", skip, size);
+ if (skip >= size)
+ return S_OK;
+ data += skip;
+ size -= skip;
- size2 = min(buf_free, size);
- hr = IDirectSoundBuffer_Lock(This->dsbuffer, This->write_pos, size2, (LPVOID *)&lpbuf1, &dwsize1, (LPVOID *)&lpbuf2, &dwsize2, 0);
+ 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);
+ 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;
+}
- return hr;
+static HRESULT WINAPI DSoundRender_ShouldDrawSampleNow(BaseRenderer *This, IMediaSample *pMediaSample, REFERENCE_TIME *pStartTime, REFERENCE_TIME *pEndTime)
+{
+ /* We time ourselves do not use the base renderers timing */
+ return S_OK;
}
-static HRESULT DSoundRender_Sample(LPVOID iface, IMediaSample * pSample)
+
+static HRESULT WINAPI DSoundRender_PrepareReceive(BaseRenderer *iface, IMediaSample *pSample)
{
- DSoundRenderImpl *This = iface;
- LPBYTE pbSrcStream = NULL;
- LONG cbSrcStream = 0;
- REFERENCE_TIME tStart, tStop;
+ 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;
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;
+}
+
+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;
- SetEvent(This->state_change);
+ 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;
return S_OK;
}
-HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv)
-{
- HRESULT hr;
- PIN_INFO piInput;
- DSoundRenderImpl * pDSoundRender;
-
- TRACE("(%p, %p)\n", pUnkOuter, ppv);
-
- *ppv = NULL;
-
- 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;
-
- /* 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);
-
- if (SUCCEEDED(hr))
- {
- hr = DirectSoundCreate8(NULL, &pDSoundRender->dsound, NULL);
- if (FAILED(hr))
- ERR("Cannot create Direct Sound object (%x)\n", hr);
- else
- IDirectSound_SetCooperativeLevel(pDSoundRender->dsound, GetDesktopWindow(), DSSCL_PRIORITY);
- }
-
- 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->state_change = CreateEventW(NULL, TRUE, TRUE, NULL);
- pDSoundRender->blocked = CreateEventW(NULL, FALSE, FALSE, NULL);
-
- if (!pDSoundRender->state_change || !pDSoundRender->blocked)
- {
- IUnknown_Release((IUnknown *)pDSoundRender);
- return HRESULT_FROM_WIN32(GetLastError());
- }
-
- *ppv = pDSoundRender;
- }
- else
- {
- if (pDSoundRender->pInputPin)
- IPin_Release((IPin*)pDSoundRender->pInputPin);
- pDSoundRender->csFilter.DebugInfo->Spare[0] = 0;
- DeleteCriticalSection(&pDSoundRender->csFilter);
- CoTaskMemFree(pDSoundRender);
- }
-
- return hr;
-}
-
-static HRESULT WINAPI DSoundRender_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
-{
- DSoundRenderImpl *This = (DSoundRenderImpl *)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;
- else if (IsEqualIID(riid, &IID_IReferenceClock))
- *ppv = &This->IReferenceClock_vtbl;
- else if (IsEqualIID(riid, &IID_IMediaSeeking))
- *ppv = &This->mediaSeeking.lpVtbl;
- else if (IsEqualIID(riid, &IID_IAMDirectSound))
- *ppv = &This->IAMDirectSound_vtbl;
-
- 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 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);
-
- TRACE("(%p)->() Release from %d\n", This, refCount + 1);
-
- if (!refCount)
- {
- IPin *pConnectedTo;
-
- if (This->pClock)
- IReferenceClock_Release(This->pClock);
-
- if (This->dsbuffer)
- IDirectSoundBuffer_Release(This->dsbuffer);
- This->dsbuffer = NULL;
- 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);
- 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)
+static VOID WINAPI DSoundRender_OnStopStreaming(BaseRenderer * iface)
{
- HRESULT hr = S_OK;
- DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
+ DSoundRenderImpl *This = impl_from_BaseRenderer(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;
+ IDirectSoundBuffer_Stop(This->dsbuffer);
+ This->writepos = This->buf_size;
+ SetEvent(This->blocked);
}
-static HRESULT WINAPI DSoundRender_Pause(IBaseFilter * iface)
+static VOID WINAPI DSoundRender_OnStartStreaming(BaseRenderer * iface)
{
- HRESULT hr = S_OK;
- DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
-
- TRACE("(%p/%p)->()\n", This, iface);
+ DSoundRenderImpl *This = impl_from_BaseRenderer(iface);
- EnterCriticalSection(&This->csFilter);
- if (This->state != State_Paused)
- {
- DWORD state = 0;
- if (This->state == State_Stopped)
- {
- This->pInputPin->end_of_stream = 0;
- }
+ TRACE("(%p)\n", This);
- if (This->dsbuffer)
+ if (This->renderer.pInputPin->pin.pConnectedTo)
+ {
+ if (This->renderer.filter.state == State_Paused)
{
- hr = IDirectSoundBuffer_GetStatus(This->dsbuffer, &state);
- if (SUCCEEDED(hr))
- {
- if (state & DSBSTATUS_PLAYING)
- hr = IDirectSoundBuffer_Stop(This->dsbuffer);
- }
+ /* Unblock our thread, state changing from paused to running doesn't need a reset for state change */
+ SetEvent(This->blocked);
}
- if (SUCCEEDED(hr))
- This->state = State_Paused;
-
+ IDirectSoundBuffer_Play(This->dsbuffer, 0, 0, DSBPLAY_LOOPING);
ResetEvent(This->blocked);
- ResetEvent(This->state_change);
}
- LeaveCriticalSection(&This->csFilter);
-
- return hr;
}
-static HRESULT WINAPI DSoundRender_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
+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;
- DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
+ WAVEFORMATEX *format;
+ DSBUFFERDESC buf_desc;
- TRACE("(%p/%p)->(%s)\n", This, iface, wine_dbgstr_longlong(tStart));
+ TRACE("(%p)->(%p)\n", This, pReceivePin);
+ dump_AM_MEDIA_TYPE(pmt);
- 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;
- }
+ 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);
- This->state = State_Running;
- }
- LeaveCriticalSection(&This->csFilter);
+ format = (WAVEFORMATEX*)pmt->pbFormat;
- return hr;
-}
+ This->buf_size = format->nAvgBytesPerSec;
-static HRESULT WINAPI DSoundRender_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
-{
- HRESULT hr;
- DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
+ 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);
- TRACE("(%p/%p)->(%d, %p)\n", This, iface, dwMilliSecsTimeout, pState);
+ 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);
- if (WaitForSingleObject(This->state_change, dwMilliSecsTimeout) == WAIT_TIMEOUT)
- hr = VFW_S_STATE_INTERMEDIATE;
- else
+ 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;
-
- 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 (FAILED(hr) && hr != VFW_E_ALREADY_CONNECTED)
{
- if (This->pClock)
- IReferenceClock_Release(This->pClock);
- This->pClock = pClock;
- if (This->pClock)
- IReferenceClock_AddRef(This->pClock);
+ if (This->dsbuffer)
+ IDirectSoundBuffer_Release(This->dsbuffer);
+ This->dsbuffer = NULL;
}
- LeaveCriticalSection(&This->csFilter);
- return S_OK;
+ return hr;
}
-static HRESULT WINAPI DSoundRender_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
+static HRESULT WINAPI DSoundRender_BreakConnect(BaseRenderer* iface)
{
- DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
+ DSoundRenderImpl *This = impl_from_BaseRenderer(iface);
- TRACE("(%p/%p)->(%p)\n", This, iface, ppClock);
+ TRACE("(%p)->()\n", iface);
- EnterCriticalSection(&This->csFilter);
- {
- *ppClock = This->pClock;
- if (This->pClock)
- IReferenceClock_AddRef(This->pClock);
+ 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);
}
- 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;
+ if (This->dsbuffer)
+ IDirectSoundBuffer_Release(This->dsbuffer);
+ This->dsbuffer = NULL;
- *pin = (IPin *)This->pInputPin;
- IPin_AddRef(*pin);
return S_OK;
}
-static HRESULT WINAPI DSoundRender_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
+static HRESULT WINAPI DSoundRender_EndOfStream(BaseRenderer* iface)
{
- DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
-
- TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
-
- return IEnumPinsImpl_Construct(ppEnum, DSoundRender_GetPin, iface);
-}
+ DSoundRenderImpl *This = impl_from_BaseRenderer(iface);
+ HRESULT hr;
-static HRESULT WINAPI DSoundRender_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
-{
- DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
+ TRACE("(%p)->()\n",iface);
- TRACE("(%p/%p)->(%s,%p)\n", This, iface, debugstr_w(Id), ppPin);
-
- FIXME("DSoundRender::FindPin(...)\n");
+ hr = BaseRendererImpl_EndOfStream(iface);
+ if (hr != S_OK)
+ {
+ ERR("%08x\n", hr);
+ return hr;
+ }
- /* FIXME: critical section */
+ hr = DSoundRender_HandleEndOfStream(This);
- return E_NOTIMPL;
+ return hr;
}
-static HRESULT WINAPI DSoundRender_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
+static HRESULT WINAPI DSoundRender_BeginFlush(BaseRenderer* iface)
{
- DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
+ DSoundRenderImpl *This = impl_from_BaseRenderer(iface);
- TRACE("(%p/%p)->(%p)\n", This, iface, pInfo);
-
- strcpyW(pInfo->achName, This->filterInfo.achName);
- pInfo->pGraph = This->filterInfo.pGraph;
+ TRACE("\n");
+ BaseRendererImpl_BeginFlush(iface);
+ SetEvent(This->blocked);
- if (pInfo->pGraph)
- IFilterGraph_AddRef(pInfo->pGraph);
-
return S_OK;
}
-static HRESULT WINAPI DSoundRender_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName)
+static HRESULT WINAPI DSoundRender_EndFlush(BaseRenderer* iface)
{
- DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
+ DSoundRenderImpl *This = impl_from_BaseRenderer(iface);
+
+ TRACE("\n");
- TRACE("(%p/%p)->(%p, %s)\n", This, iface, pGraph, debugstr_w(pName));
+ BaseRendererImpl_EndFlush(iface);
+ if (This->renderer.filter.state != State_Stopped)
+ ResetEvent(This->blocked);
- EnterCriticalSection(&This->csFilter);
+ if (This->dsbuffer)
{
- if (pName)
- strcpyW(This->filterInfo.achName, pName);
- else
- *This->filterInfo.achName = '\0';
- This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
+ 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;
}
- 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,
- DSoundRender_Release,
- DSoundRender_GetClassID,
- DSoundRender_Stop,
- DSoundRender_Pause,
- DSoundRender_Run,
- DSoundRender_GetState,
- DSoundRender_SetSyncSource,
- DSoundRender_GetSyncSource,
- DSoundRender_EnumPins,
- DSoundRender_FindPin,
- DSoundRender_QueryFilterInfo,
- DSoundRender_JoinFilterGraph,
- DSoundRender_QueryVendorInfo
+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,
};
-static HRESULT WINAPI DSoundRender_InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
+HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv)
{
- InputPin *This = (InputPin *)iface;
- PIN_DIRECTION pindirReceive;
- DSoundRenderImpl *DSImpl;
- HRESULT hr = S_OK;
+ HRESULT hr;
+ DSoundRenderImpl * pDSoundRender;
- TRACE("(%p)->(%p, %p)\n", This, pReceivePin, pmt);
- dump_AM_MEDIA_TYPE(pmt);
+ TRACE("(%p, %p)\n", pUnkOuter, ppv);
- EnterCriticalSection(This->pin.pCritSec);
- {
- DSImpl = (DSoundRenderImpl*)This->pin.pinInfo.pFilter;
- DSImpl->rtLastStop = -1;
+ *ppv = NULL;
- if (This->pin.pConnectedTo)
- hr = VFW_E_ALREADY_CONNECTED;
+ if (pUnkOuter)
+ return CLASS_E_NOAGGREGATION;
- if (SUCCEEDED(hr) && This->pin.fnQueryAccept(This->pin.pUserData, pmt) != S_OK)
- hr = VFW_E_TYPE_NOT_ACCEPTED;
+ pDSoundRender = CoTaskMemAlloc(sizeof(DSoundRenderImpl));
+ if (!pDSoundRender)
+ return E_OUTOFMEMORY;
+ ZeroMemory(pDSoundRender, sizeof(DSoundRenderImpl));
- if (SUCCEEDED(hr))
- {
- IPin_QueryDirection(pReceivePin, &pindirReceive);
+ hr = BaseRenderer_Init(&pDSoundRender->renderer, &DSoundRender_Vtbl, (IUnknown*)pDSoundRender, &CLSID_DSoundRender, (DWORD_PTR)(__FILE__ ": DSoundRenderImpl.csFilter"), &BaseFuncTable);
- if (pindirReceive != PINDIR_OUTPUT)
- {
- ERR("Can't connect from non-output pin\n");
- hr = VFW_E_INVALID_DIRECTION;
- }
- }
+ 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))
- {
- WAVEFORMATEX *format;
+ if (SUCCEEDED(hr))
+ {
+ hr = DirectSoundCreate8(NULL, &pDSoundRender->dsound, NULL);
+ if (FAILED(hr))
+ ERR("Cannot create Direct Sound object (%x)\n", hr);
+ else
+ hr = IDirectSound_SetCooperativeLevel(pDSoundRender->dsound, GetDesktopWindow(), DSSCL_PRIORITY);
+ if (SUCCEEDED(hr)) {
+ IDirectSoundBuffer *buf;
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;
+ 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))
- {
- CopyMediaType(&This->pin.mtCurrent, pmt);
- This->pin.pConnectedTo = pReceivePin;
- IPin_AddRef(pReceivePin);
- }
- else if (hr != VFW_E_ALREADY_CONNECTED)
+ if (SUCCEEDED(hr))
+ {
+ pDSoundRender->blocked = CreateEventW(NULL, TRUE, TRUE, NULL);
+
+ if (!pDSoundRender->blocked || FAILED(hr))
{
- if (DSImpl->dsbuffer)
- IDirectSoundBuffer_Release(DSImpl->dsbuffer);
- DSImpl->dsbuffer = NULL;
+ IUnknown_Release((IUnknown *)pDSoundRender);
+ return HRESULT_FROM_WIN32(GetLastError());
}
+
+ *ppv = pDSoundRender;
+ }
+ else
+ {
+ BaseRendererImpl_Release(&pDSoundRender->renderer.filter.IBaseFilter_iface);
+ CoTaskMemFree(pDSoundRender);
}
- 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)
+static HRESULT WINAPI DSoundRender_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
{
- InputPin* This = (InputPin*)iface;
- DSoundRenderImpl *me = (DSoundRenderImpl*)This->pin.pinInfo.pFilter;
- IMediaEventSink* pEventSink;
- HRESULT hr;
+ DSoundRenderImpl *This = impl_from_IBaseFilter(iface);
+ TRACE("(%p, %p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
- EnterCriticalSection(This->pin.pCritSec);
+ *ppv = NULL;
- TRACE("(%p/%p)->()\n", This, iface);
- hr = InputPin_EndOfStream(iface);
- if (hr != S_OK)
+ if (IsEqualIID(riid, &IID_IBasicAudio))
+ *ppv = &This->basicAudio.IBasicAudio_iface;
+ else if (IsEqualIID(riid, &IID_IReferenceClock))
+ *ppv = &This->IReferenceClock_iface;
+ else if (IsEqualIID(riid, &IID_IAMDirectSound))
+ *ppv = &This->IAMDirectSound_iface;
+ else if (IsEqualIID(riid, &IID_IAMFilterMiscFlags))
+ *ppv = &This->IAMFilterMiscFlags_iface;
+ else
{
- ERR("%08x\n", hr);
- LeaveCriticalSection(This->pin.pCritSec);
- return hr;
+ HRESULT hr;
+ hr = BaseRendererImpl_QueryInterface(iface, riid, ppv);
+ if (SUCCEEDED(hr))
+ return hr;
}
- hr = IFilterGraph_QueryInterface(me->filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink);
- if (SUCCEEDED(hr))
+ if (*ppv)
{
- 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);
+ IUnknown_AddRef((IUnknown *)(*ppv));
+ return S_OK;
}
- LeaveCriticalSection(This->pin.pCritSec);
- return hr;
+ if (!IsEqualIID(riid, &IID_IPin) && !IsEqualIID(riid, &IID_IVideoWindow))
+ FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
+
+ return E_NOINTERFACE;
}
-static HRESULT WINAPI DSoundRender_InputPin_BeginFlush(IPin * iface)
+static ULONG WINAPI DSoundRender_Release(IBaseFilter * iface)
{
- InputPin *This = (InputPin *)iface;
- DSoundRenderImpl *pFilter = (DSoundRenderImpl *)This->pin.pinInfo.pFilter;
- HRESULT hr;
- LPBYTE buffer;
- DWORD size;
+ DSoundRenderImpl *This = impl_from_IBaseFilter(iface);
+ ULONG refCount = BaseRendererImpl_Release(iface);
- TRACE("\n");
-
- EnterCriticalSection(This->pin.pCritSec);
- hr = InputPin_BeginFlush(iface);
+ TRACE("(%p)->() Release from %d\n", This, refCount + 1);
- if (pFilter->dsbuffer)
+ if (!refCount)
{
- IDirectSoundBuffer_Stop(pFilter->dsbuffer);
+ if (This->threadid) {
+ PostThreadMessageW(This->threadid, WM_APP, 0, 0);
+ WaitForSingleObject(This->advisethread, INFINITE);
+ CloseHandle(This->advisethread);
+ }
- /* 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;
+ if (This->dsbuffer)
+ IDirectSoundBuffer_Release(This->dsbuffer);
+ This->dsbuffer = NULL;
+ if (This->dsound)
+ IDirectSound_Release(This->dsound);
+ This->dsound = NULL;
- 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);
- }
+ BasicAudio_Destroy(&This->basicAudio);
+ CloseHandle(This->blocked);
- if (pFilter->state == State_Paused)
- SetEvent(pFilter->blocked);
- LeaveCriticalSection(This->pin.pCritSec);
+ TRACE("Destroying Audio Renderer\n");
+ CoTaskMemFree(This);
- return hr;
+ return 0;
+ }
+ else
+ return refCount;
}
-static HRESULT WINAPI DSoundRender_InputPin_EndFlush(IPin * iface)
+static HRESULT WINAPI DSoundRender_Pause(IBaseFilter * iface)
{
- InputPin *This = (InputPin *)iface;
- DSoundRenderImpl *pFilter = (DSoundRenderImpl *)This->pin.pinInfo.pFilter;
- HRESULT hr;
+ HRESULT hr = S_OK;
+ DSoundRenderImpl *This = (DSoundRenderImpl *)iface;
- TRACE("\n");
+ TRACE("(%p/%p)->()\n", This, iface);
- EnterCriticalSection(This->pin.pCritSec);
- hr = InputPin_EndFlush(iface);
+ EnterCriticalSection(&This->renderer.csRenderLock);
+ if (This->renderer.filter.state != State_Paused)
+ {
+ if (This->renderer.filter.state == State_Stopped)
+ {
+ if (This->renderer.pInputPin->pin.pConnectedTo)
+ ResetEvent(This->renderer.evComplete);
+ This->renderer.pInputPin->end_of_stream = 0;
+ }
+
+ hr = IDirectSoundBuffer_Stop(This->dsbuffer);
+ if (SUCCEEDED(hr))
+ This->renderer.filter.state = State_Paused;
- if (pFilter->state == State_Paused)
- SetEvent(pFilter->blocked);
- LeaveCriticalSection(This->pin.pCritSec);
+ ResetEvent(This->blocked);
+ ResetEvent(This->renderer.RenderEvent);
+ }
+ ResetEvent(This->renderer.ThreadSignal);
+ LeaveCriticalSection(&This->renderer.csRenderLock);
return hr;
}
-static const IPinVtbl DSoundRender_InputPin_Vtbl =
+static const IBaseFilterVtbl DSoundRender_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
+ DSoundRender_QueryInterface,
+ BaseFilterImpl_AddRef,
+ DSoundRender_Release,
+ BaseFilterImpl_GetClassID,
+ BaseRendererImpl_Stop,
+ DSoundRender_Pause,
+ 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);
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);
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);
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);
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;
}
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);
-
- FIXME("(%p/%p)->(%p): stub!\n", This, iface, (void*)dwAdviseCookie);
+ DSoundRenderImpl *This = impl_from_IReferenceClock(iface);
- 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 =
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);
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);
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);
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);
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);
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);
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);
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);
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
+};
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;
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;
}
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);
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
{
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]);
}
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;
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);
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
-};
*
* 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
typedef struct EnumMonikerImpl
{
- const IEnumMonikerVtbl *lpVtbl;
+ IEnumMoniker IEnumMoniker_iface;
LONG ref;
IMoniker ** ppMoniker;
ULONG nMonikerCount;
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)
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;
}
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;
*/
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;
*/
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);
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);
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);
static HRESULT WINAPI EnumMonikerImpl_Reset(LPENUMMONIKER iface)
{
- EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
+ EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
TRACE("(%p)->()\n", iface);
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)
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;
}
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);
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);
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;
static HRESULT WINAPI IEnumRegFiltersImpl_Reset(IEnumRegFilters * iface)
{
- IEnumRegFiltersImpl *This = (IEnumRegFiltersImpl *)iface;
+ IEnumRegFiltersImpl *This = impl_from_IEnumRegFilters(iface);
TRACE("(%p)\n", iface);
--- /dev/null
+/*
+ * 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);
+}
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;
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);
if (!(wszPatternString = strchrW(wszPatternString, ',')))
hr = E_INVALIDARG;
-
- wszPatternString++; /* skip ',' */
+ else
+ wszPatternString++; /* skip ',' */
}
if (hr == S_OK)
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;
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);
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;
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;
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 (strcmpW(wszValueName, source_filter_name)==0) {
+ HeapFree(GetProcessHeap(), 0, wszPatternString);
+ continue;
+ }
+
/* if it is not the source filter value */
- if (strcmpW(wszValueName, wszSourceFilter))
+ if (process_pattern_string(wszPatternString, pReader) == S_OK)
{
- 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)
{
- if (SUCCEEDED(CLSIDFromString(wszMajorKeyName, majorType)) &&
- SUCCEEDED(CLSIDFromString(wszMinorKeyName, minorType)))
- bFound = TRUE;
+ /* Look up the source filter key */
+ if (RegQueryValueExW(hkeyMinor, source_filter_name, NULL, NULL, (LPBYTE)wszSourceFilterKeyName, &dwSourceFilterKeyNameLen))
+ break;
+ if (FAILED(CLSIDFromString(wszSourceFilterKeyName, sourceFilter)))
+ break;
}
- }
- HeapFree(GetProcessHeap(), 0, wszPatternString);
+ bFound = TRUE;
+ } else
+ HeapFree(GetProcessHeap(), 0, wszPatternString);
}
CloseHandle(hkeyMinor);
}
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;
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;
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);
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)
{
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);
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);
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);
-
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI AsyncReader_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
-{
- AsyncReader *This = (AsyncReader *)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;
-}
-
-static HRESULT WINAPI AsyncReader_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName)
-{
- AsyncReader *This = (AsyncReader *)iface;
+ AsyncReader *This = impl_from_IBaseFilter(iface);
+ TRACE("(%s, %p)\n", debugstr_w(Id), ppPin);
- TRACE("(%p, %s)\n", pGraph, debugstr_w(pName));
+ if (!Id || !ppPin)
+ return E_POINTER;
- if (pName)
- strcpyW(This->filterInfo.achName, pName);
- else
- *This->filterInfo.achName = 0;
- This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
+ if (strcmpW(Id, wszOutputPinName))
+ {
+ *ppPin = NULL;
+ return VFW_E_NOT_FOUND;
+ }
+ *ppPin = This->pOutputPin;
+ IPin_AddRef(*ppPin);
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)
}
/* 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);
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);
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 */
HANDLE *handle_list;
} FileAsyncReader;
-static inline FileAsyncReader *impl_from_IAsyncReader( IAsyncReader *iface )
+static inline FileAsyncReader *impl_from_IPin(IPin *iface)
+{
+ return CONTAINING_RECORD(iface, FileAsyncReader, pin.pin.IPin_iface);
+}
+
+static inline FileAsyncReader *impl_from_BasePin(BasePin *iface)
{
- return (FileAsyncReader *)((char*)iface - FIELD_OFFSET(FileAsyncReader, lpVtblAR));
+ return CONTAINING_RECORD(iface, FileAsyncReader, pin.pin);
}
-static HRESULT AcceptProcAFR(LPVOID iface, const AM_MEDIA_TYPE *pmt)
+static inline FileAsyncReader *impl_from_BaseOutputPin(BaseOutputPin *iface)
{
- AsyncReader *This = 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;
else if (IsEqualIID(riid, &IID_IPin))
*ppv = This;
else if (IsEqualIID(riid, &IID_IAsyncReader))
- *ppv = &This->lpVtblAR;
+ *ppv = &This->IAsyncReader_iface;
if (*ppv)
{
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;
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);
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))
{
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;
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");
}
{
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
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
{
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
/* 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);
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());
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
+};
* 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
*/
#include <config.h>
-//#include <stdarg.h>
+#include <stdarg.h>
#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 <wine/debug.h>
#include "quartz_private.h"
-#include <shlwapi.h>
-//#include "ole2.h"
-//#include "olectl.h"
-//#include "strmif.h"
-//#include "vfwmsgs.h"
-//#include "evcode.h"
+#include "ole2.h"
+#include "olectl.h"
+#include <strmif.h>
+#include "vfwmsgs.h"
+#include "evcode.h"
#include <wine/unicode.h>
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.
} 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;
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);
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);
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;
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);
+
+ TRACE("(%p/%p)->()\n", This, iface);
- return Filtergraph_Release(This);
+ 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;
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;
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)
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)
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);
/* 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 */
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;
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);
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)->() live sources not handled properly!\n", iface, This);
- TRACE("(%p/%p)->() semi-stub\n", iface, This);
+ 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;
+ }
- hr = CoCreateInstance(&CLSID_SystemClock, NULL, CLSCTX_INPROC_SERVER, &IID_IReferenceClock, (LPVOID*)&pClock);
+ 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;
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);
/*** 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;
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);
{
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;
}
+ 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;
}
- hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IBaseFilter, (LPVOID*)&pfilter);
- if (FAILED(hr)) {
- WARN("Unable to create filter (%x), trying next one\n", hr);
- 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));
hr = GetInternalConnections(pfilter, ppinfilter, &ppins, &nb);
if (SUCCEEDED(hr)) {
- unsigned int i;
if (nb == 0) {
IPin_Disconnect(ppinfilter);
IPin_Disconnect(ppinOut);
IFilterGraph2_RemoveFilter(iface, pfilter);
IBaseFilter_Release(pfilter);
}
+ while (++i < nb) IPin_Release(ppins[i]);
+ CoTaskMemFree(ppins);
}
out:
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
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;
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);
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);
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;
return hr;
}
+static HRESULT CreateFilterInstanceAndLoadFile(GUID* clsid, LPCOLESTR pszFileName, IBaseFilter **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))
+ 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;
+}
+
/* Some filters implement their own asynchronous reader (Theoretically they all should, try to load it first */
static HRESULT GetFileSourceFilter(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;
+ HRESULT hr;
+ GUID clsid;
+ IAsyncReader * pReader = NULL;
+ IFileSourceFilter* pSource = NULL;
+ IPin * pOutputPin = NULL;
+ static const WCHAR wszOutputPinName[] = { 'O','u','t','p','u','t',0 };
- lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszReg, 0, KEY_READ, &extkey);
- hr = HRESULT_FROM_WIN32(lRet);
+ /* Try to find a match without reading the file first */
+ hr = GetClassMediaFile(NULL, pszFileName, NULL, NULL, &clsid);
- if (SUCCEEDED(hr))
+ 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))
{
- 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;
+ IBaseFilter_Release(*filter);
+ return hr;
+ }
- if (!ext)
- {
- CloseHandle(extkey);
- return E_FAIL;
- }
+ hr = IFileSourceFilter_Load(pSource, pszFileName, NULL);
+ IFileSourceFilter_Release(pSource);
+ if (FAILED(hr))
+ {
+ IBaseFilter_Release(*filter);
+ return hr;
+ }
- lRet = RegOpenKeyExW(extkey, ext, 0, KEY_READ, &pathkey);
- hr = HRESULT_FROM_WIN32(lRet);
- CloseHandle(extkey);
- if (FAILED(hr))
- return hr;
+ hr = IBaseFilter_FindPin(*filter, wszOutputPinName, &pOutputPin);
+ if (FAILED(hr))
+ {
+ IBaseFilter_Release(*filter);
+ return hr;
+ }
- lRet = RegQueryValueExW(pathkey, filtersource, NULL, NULL, (LPBYTE)clsid_key, &size);
- hr = HRESULT_FROM_WIN32(lRet);
- CloseHandle(pathkey);
- if (FAILED(hr))
- return hr;
+ hr = IPin_QueryInterface(pOutputPin, &IID_IAsyncReader, (LPVOID *)&pReader);
+ IPin_Release(pOutputPin);
+ if (FAILED(hr))
+ {
+ IBaseFilter_Release(*filter);
+ return hr;
+ }
- CLSIDFromString(clsid_key, &clsid);
+ /* Try again find a match */
+ hr = GetClassMediaFile(pReader, pszFileName, NULL, NULL, &clsid);
+ IAsyncReader_Release(pReader);
- 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);
- }
+ if (!hr)
+ {
+ /* Release the AsyncReader filter and create the matching one */
+ IBaseFilter_Release(*filter);
+ return CreateFilterInstanceAndLoadFile(&clsid, pszFileName, filter);
}
- if (FAILED(hr))
- *filter = NULL;
- return hr;
+
+ /* Return the AsyncReader filter */
+ return S_OK;
}
-static HRESULT WINAPI FilterGraph2_AddSourceFilter(IFilterGraph2 *iface,
- LPCWSTR lpcwstrFileName,
- LPCWSTR lpcwstrFilterName,
- IBaseFilter **ppFilter) {
- ICOM_THIS_MULTI(IFilterGraphImpl, IFilterGraph2_vtbl, iface);
+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;
/* 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;
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);
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);
/*** 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);
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);
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]);
}
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);
}
}
-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;
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 */
}
/*** IMediaControl methods ***/
-static HRESULT WINAPI MediaControl_Run(IMediaControl *iface) {
- ICOM_THIS_MULTI(IFilterGraphImpl, IMediaControl_vtbl, iface);
- TRACE("(%p/%p)->()\n", This, iface);
+static HRESULT WINAPI MediaControl_Run(IMediaControl *iface)
+{
+ IFilterGraphImpl *This = impl_from_IMediaControl(iface);
- if (This->state == State_Running) return S_OK;
+ TRACE("(%p/%p)->()\n", This, iface);
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);
- TRACE("(%p/%p)->()\n", This, iface);
+static HRESULT WINAPI MediaControl_Pause(IMediaControl *iface)
+{
+ IFilterGraphImpl *This = impl_from_IMediaControl(iface);
- if (This->state == State_Paused) return S_OK;
+ TRACE("(%p/%p)->()\n", This, iface);
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);
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);
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);
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)
}
/*** 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)
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)
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;
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;
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;
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)
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;
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);
return E_POINTER;
EnterCriticalSection(&This->cs);
- *pDuration = -1;
+ *pDuration = 0;
hr = all_renderers_seek(This, FoundDuration, (DWORD_PTR)pDuration);
LeaveCriticalSection(&This->cs);
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);
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));
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);
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;
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)
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);
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);
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 ***/
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)
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)
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;
}
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;
}
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;
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;
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;
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;
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;
}
/*** 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;
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;
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;
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;
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);
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);
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);
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);
}
/*** 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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
}
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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;
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);
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);
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);
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);
/*** 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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
}
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
}
/*** 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);
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);
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);
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);
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);
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);
}
/*** 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);
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);
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);
};
-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);
+}
+
+static HRESULT WINAPI MediaFilter_QueryInterface(IMediaFilter *iface, REFIID riid, void **ppv)
+{
+ IFilterGraphImpl *This = impl_from_IMediaFilter(iface);
- return Filtergraph_QueryInterface(This, riid, ppv);
+ 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)
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;
This->refClock = pClock;
if (This->refClock)
IReferenceClock_AddRef(This->refClock);
+ This->defaultclock = FALSE;
if (This->HandleEcClockChanged)
{
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);
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);
+}
+
+static HRESULT WINAPI MediaEventSink_QueryInterface(IMediaEventSink *iface, REFIID riid, void **ppv)
+{
+ IFilterGraphImpl *This = impl_from_IMediaEventSink(iface);
- return Filtergraph_QueryInterface(This, riid, ppv);
+ 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);
MediaEventSink_Notify
};
-static HRESULT WINAPI GraphConfig_QueryInterface(IGraphConfig *iface, REFIID riid, LPVOID *ppv)
+static inline IFilterGraphImpl *impl_from_IGraphConfig(IGraphConfig *iface)
+{
+ return CONTAINING_RECORD(iface, IFilterGraphImpl, IGraphConfig_iface);
+}
+
+static HRESULT WINAPI GraphConfig_QueryInterface(IGraphConfig *iface, REFIID riid, void **ppv)
{
- ICOM_THIS_MULTI(IFilterGraphImpl, IGraphConfig_vtbl, iface);
+ IFilterGraphImpl *This = impl_from_IGraphConfig(iface);
- return Filtergraph_QueryInterface(This, riid, ppv);
+ 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);
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;
}
GraphConfig_RemoveFilterEx
};
-static const IUnknownVtbl IInner_VTable =
+static inline IFilterGraphImpl *impl_from_IGraphVersion(IGraphVersion *iface)
{
- FilterGraphInner_QueryInterface,
- FilterGraphInner_AddRef,
- FilterGraphInner_Release
-};
+ return CONTAINING_RECORD(iface, IFilterGraphImpl, IGraphVersion_iface);
+}
-static HRESULT Filtergraph_QueryInterface(IFilterGraphImpl *This,
- REFIID riid,
- LPVOID * ppv) {
- if (This->bAggregatable)
- This->bUnkOuterValid = TRUE;
+static HRESULT WINAPI GraphVersion_QueryInterface(IGraphVersion *iface, REFIID riid, void **ppv)
+{
+ IFilterGraphImpl *This = impl_from_IGraphVersion(iface);
- if (This->pUnkOuter)
- {
- if (This->bAggregatable)
- return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv);
+ return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
+}
- if (IsEqualIID(riid, &IID_IUnknown))
- {
- HRESULT hr;
+static ULONG WINAPI GraphVersion_AddRef(IGraphVersion *iface)
+{
+ IFilterGraphImpl *This = impl_from_IGraphVersion(iface);
- 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;
- }
+ return IUnknown_AddRef(This->outer_unk);
+}
- *ppv = NULL;
- return E_NOINTERFACE;
- }
+static ULONG WINAPI GraphVersion_Release(IGraphVersion *iface)
+{
+ IFilterGraphImpl *This = impl_from_IGraphVersion(iface);
- return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
+ return IUnknown_Release(This->outer_unk);
}
-static ULONG Filtergraph_AddRef(IFilterGraphImpl *This) {
- if (This->pUnkOuter && This->bUnkOuterValid)
- return IUnknown_AddRef(This->pUnkOuter);
- return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
-}
+static HRESULT WINAPI GraphVersion_QueryVersion(IGraphVersion *iface, LONG *pVersion)
+{
+ IFilterGraphImpl *This = impl_from_IGraphVersion(iface);
-static ULONG Filtergraph_Release(IFilterGraphImpl *This) {
- if (This->pUnkOuter && This->bUnkOuterValid)
- return IUnknown_Release(This->pUnkOuter);
- return IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
+ 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,
+ FilterGraphInner_AddRef,
+ FilterGraphInner_Release
+};
+
/* This is the only function that actually creates a FilterGraph class... */
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;
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);
CoTaskMemFree(fimpl);
return hr;
}
- IFilterGraph2_SetDefaultSyncSource((IFilterGraph2*)fimpl);
- *ppObj = fimpl;
+ *ppObj = &fimpl->IUnknown_inner;
return S_OK;
}
/*
- * IFilterMapper & IFilterMapper2 Implementations
+ * IFilterMapper & IFilterMapper3 Implementations
*
* Copyright 2003 Robert Shearman
* Copyright 2004 Christian Costa
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#define NONAMELESSUNION
-#define NONAMELESSSTRUCT
//#include <stdarg.h>
//#include "windef.h"
//#include "strmif.h"
#include <wine/unicode.h>
//#include "uuids.h"
+#include <initguid.h>
+#include <fil_data.h>
#include <wine/debug.h>
#define ARRAYSIZE(array) (sizeof(array)/sizeof((array)[0]))
-/* Unexposed IAMFilterData interface */
-typedef struct IAMFilterData IAMFilterData;
-
-typedef struct IAMFilterDataVtbl
+typedef struct FilterMapper3Impl
{
- BEGIN_INTERFACE
-
- /*** 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
+ IUnknown IUnknown_inner;
+ IFilterMapper3 IFilterMapper3_iface;
+ IFilterMapper IFilterMapper_iface;
+ IAMFilterData IAMFilterData_iface;
+ IUnknown *outer_unk;
+ LONG ref;
+} FilterMapper3Impl;
+
+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 }
-};
-
+ return CONTAINING_RECORD(iface, FilterMapper3Impl, IFilterMapper3_iface);
+}
-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 )
+static inline FilterMapper3Impl *impl_from_IFilterMapper( IFilterMapper *iface )
{
- return (FilterMapper2Impl *)((char*)iface - FIELD_OFFSET(FilterMapper2Impl, lpVtblFilterMapper));
+ return CONTAINING_RECORD(iface, FilterMapper3Impl, IFilterMapper_iface);
}
-static inline FilterMapper2Impl *impl_from_IAMFilterData( IAMFilterData *iface )
+static inline FilterMapper3Impl *impl_from_IAMFilterData( IAMFilterData *iface )
{
- return (FilterMapper2Impl *)((char*)iface - FIELD_OFFSET(FilterMapper2Impl, lpVtblAMFilterData));
+ return CONTAINING_RECORD(iface, FilterMapper3Impl, IAMFilterData_iface);
}
-static inline FilterMapper2Impl *impl_from_inner_IUnknown( IUnknown *iface )
+static inline FilterMapper3Impl *impl_from_IUnknown( IUnknown *iface )
{
- return (FilterMapper2Impl *)((char*)iface - FIELD_OFFSET(FilterMapper2Impl, IInner_vtbl));
+ return CONTAINING_RECORD(iface, FilterMapper3Impl, IUnknown_inner);
}
static const WCHAR wszClsidSlash[] = {'C','L','S','I','D','\\',0};
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);
- TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
+ FilterMapper3Impl *This = impl_from_IUnknown(iface);
- if (This->bAggregatable)
- This->bUnkOuterValid = TRUE;
+ TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
*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)
{
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 =
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;
-
- if (This->bAggregatable)
- This->bUnkOuterValid = TRUE;
+ FilterMapper3Impl *This = impl_from_IFilterMapper3(iface);
- 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)
return hr;
}
-static HRESULT WINAPI FilterMapper2_UnregisterFilter(
- IFilterMapper2 * iface,
+static HRESULT WINAPI FilterMapper3_UnregisterFilter(
+ IFilterMapper3 * iface,
const CLSID *pclsidCategory,
const OLECHAR *szInstance,
REFCLSID Filter)
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';
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++)
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,
/* 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;
* 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,
/* 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)) &&
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 ***/
CLSID clsOutMaj,
CLSID clsOutSub)
{
- FilterMapper2Impl *This = impl_from_IFilterMapper(iface);
+ FilterMapper3Impl *This = impl_from_IFilterMapper(iface);
GUID InputType[2];
GUID OutputType[2];
IEnumMoniker* ppEnumMoniker;
*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;
/*** 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 ***/
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))
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);
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;
+}
*
* 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
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;
{ &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 },
{ &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)
}
-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);
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;
}
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;
}
}
*/
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);
}
/***********************************************************************
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;
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)
{
assert(fnAlloc && fnFree && fnDestroyed);
- pMemAlloc->lpVtbl = &BaseMemAllocator_VTable;
+ pMemAlloc->IMemAllocator_iface.lpVtbl = &BaseMemAllocator_VTable;
pMemAlloc->ref = 1;
ZeroMemory(&pMemAlloc->props, sizeof(pMemAlloc->props));
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;
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);
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);
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);
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);
static HRESULT WINAPI BaseMemAllocator_Commit(IMemAllocator * iface)
{
- BaseMemAllocator *This = (BaseMemAllocator *)iface;
+ BaseMemAllocator *This = impl_from_IMemAllocator(iface);
HRESULT hr;
TRACE("(%p)->()\n", This);
static HRESULT WINAPI BaseMemAllocator_Decommit(IMemAllocator * iface)
{
- BaseMemAllocator *This = (BaseMemAllocator *)iface;
+ BaseMemAllocator *This = impl_from_IMemAllocator(iface);
HRESULT hr;
TRACE("(%p)->()\n", This);
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.
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);
}
}
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 */
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));
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)
{
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);
static LONG WINAPI StdMediaSample2_GetSize(IMediaSample2 * iface)
{
- StdMediaSample2 *This = (StdMediaSample2 *)iface;
+ StdMediaSample2 *This = impl_from_IMediaSample2(iface);
TRACE("StdMediaSample2_GetSize()\n");
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);
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);
static HRESULT WINAPI StdMediaSample2_IsSyncPoint(IMediaSample2 * iface)
{
- StdMediaSample2 *This = (StdMediaSample2 *)iface;
+ StdMediaSample2 *This = impl_from_IMediaSample2(iface);
TRACE("(%p)->()\n", 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");
static HRESULT WINAPI StdMediaSample2_IsPreroll(IMediaSample2 * iface)
{
- StdMediaSample2 *This = (StdMediaSample2 *)iface;
+ StdMediaSample2 *This = impl_from_IMediaSample2(iface);
TRACE("(%p)->()\n", 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");
static LONG WINAPI StdMediaSample2_GetActualDataLength(IMediaSample2 * iface)
{
- StdMediaSample2 *This = (StdMediaSample2 *)iface;
+ StdMediaSample2 *This = impl_from_IMediaSample2(iface);
TRACE("(%p)->()\n", 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);
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);
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);
static HRESULT WINAPI StdMediaSample2_IsDiscontinuity(IMediaSample2 * iface)
{
- StdMediaSample2 *This = (StdMediaSample2 *)iface;
+ StdMediaSample2 *This = impl_from_IMediaSample2(iface);
TRACE("(%p)->()\n", 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");
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);
*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);
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);
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);
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;
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;
/* 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 */
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))
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);
//#include <math.h>
#include "quartz_private.h"
-#include "control_private.h"
#include "pin.h"
//#include "uuids.h"
#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 */
static HRESULT parse_header(BYTE *header, LONGLONG *plen, LONGLONG *pduration)
{
- LONGLONG duration;
-
int bitrate_index, freq_index, lsf = 1, mpeg1, layer, padding, bitrate, length;
+ LONGLONG duration;
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;
}
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)
+ 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]<<lsf) + padding;
else
- length = 4 * (12 * bitrate / freqs[freq_index] + padding);
+ {
+ ERR("Impossible layer %d\n", layer);
+ return E_INVALIDARG;
+ }
duration = (ULONGLONG)10000000 * (ULONGLONG)(length) / (ULONGLONG)(bitrate/8);
*plen = length;
static HRESULT FillBuffer(MPEGSplitterImpl *This, IMediaSample *pCurrentSample)
{
- Parser_OutputPin * pOutputPin = (Parser_OutputPin*)This->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);
IMediaSample_GetPointer(pCurrentSample, &fbuf);
/* Find the next valid header.. it <SHOULD> 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 */
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);
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)
{
}
}
- 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;
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;
}
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 */
/* 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 */
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;
}
/* 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:
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;
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)
{
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);
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))
{
#define NONAMELESSSTRUCT
#define NONAMELESSUNION
#include "quartz_private.h"
-#include "control_private.h"
#include "pin.h"
//#include "uuids.h"
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);
+ TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), 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;
- }
+ if (IsEqualIID(riid, &IID_IUnknown))
+ *ppv = &This->IUnknown_inner;
+ else if (IsEqualIID(riid, &IID_IAMFilterMiscFlags))
+ *ppv = &This->IAMFilterMiscFlags_iface;
else
{
- pNullRenderer->csFilter.DebugInfo->Spare[0] = 0;
- DeleteCriticalSection(&pNullRenderer->csFilter);
- CoTaskMemFree(pNullRenderer);
+ HRESULT hr;
+ hr = BaseRendererImpl_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
+ if (SUCCEEDED(hr))
+ return hr;
}
- 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;
-
if (*ppv)
{
- IUnknown_AddRef((IUnknown *)(*ppv));
+ IUnknown_AddRef((IUnknown *)*ppv);
return S_OK;
}
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 =
NullRendererInner_Release
};
-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);
-}
-
-static ULONG WINAPI NullRenderer_AddRef(IBaseFilter * iface)
+static inline NullRendererImpl *impl_from_IBaseFilter(IBaseFilter *iface)
{
- NullRendererImpl *This = (NullRendererImpl *)iface;
-
- if (This->pUnkOuter && This->bUnkOuterValid)
- return IUnknown_AddRef(This->pUnkOuter);
- return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
+ return CONTAINING_RECORD(iface, NullRendererImpl, renderer.filter.IBaseFilter_iface);
}
-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)
+static HRESULT WINAPI NullRenderer_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
{
- NullRendererImpl *This = (NullRendererImpl *)iface;
-
- TRACE("(%p/%p)->(%p)\n", This, iface, pClsid);
-
- *pClsid = CLSID_NullRenderer;
-
- return S_OK;
+ NullRendererImpl *This = impl_from_IBaseFilter(iface);
+ return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
}
-/** IMediaFilter methods **/
-
-static HRESULT WINAPI NullRenderer_Stop(IBaseFilter * iface)
+static ULONG WINAPI NullRenderer_AddRef(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;
+ NullRendererImpl *This = impl_from_IBaseFilter(iface);
+ return IUnknown_AddRef(This->outer_unk);
}
-static HRESULT WINAPI NullRenderer_Pause(IBaseFilter * iface)
+static ULONG WINAPI NullRenderer_Release(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;
+ NullRendererImpl *This = impl_from_IBaseFilter(iface);
+ return IUnknown_Release(This->outer_unk);
}
-static HRESULT WINAPI NullRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
+static const IBaseFilterVtbl NullRenderer_Vtbl =
{
- 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;
-}
+ NullRenderer_QueryInterface,
+ NullRenderer_AddRef,
+ NullRenderer_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
+};
-static HRESULT WINAPI NullRenderer_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
+static NullRendererImpl *impl_from_IAMFilterMiscFlags(IAMFilterMiscFlags *iface)
{
- 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;
+ return CONTAINING_RECORD(iface, NullRendererImpl, IAMFilterMiscFlags_iface);
}
-static HRESULT WINAPI NullRenderer_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
+static HRESULT WINAPI AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid,
+ void **ppv)
{
- 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;
+ NullRendererImpl *This = impl_from_IAMFilterMiscFlags(iface);
+ return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
}
-static HRESULT WINAPI NullRenderer_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
+static ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface)
{
- 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;
+ NullRendererImpl *This = impl_from_IAMFilterMiscFlags(iface);
+ return IUnknown_AddRef(This->outer_unk);
}
-/** IBaseFilter implementation **/
-
-static HRESULT NullRenderer_GetPin(IBaseFilter *iface, ULONG pos, IPin **pin, DWORD *lastsynctick)
+static ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface)
{
- 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;
+ NullRendererImpl *This = impl_from_IAMFilterMiscFlags(iface);
+ return IUnknown_Release(This->outer_unk);
}
-static HRESULT WINAPI NullRenderer_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
+static ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface)
{
- NullRendererImpl *This = (NullRendererImpl *)iface;
-
- TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
-
- return IEnumPinsImpl_Construct(ppEnum, NullRenderer_GetPin, iface);
+ return AM_FILTER_MISC_FLAGS_IS_RENDERER;
}
-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 const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = {
+ AMFilterMiscFlags_QueryInterface,
+ AMFilterMiscFlags_AddRef,
+ AMFilterMiscFlags_Release,
+ AMFilterMiscFlags_GetMiscFlags
+};
-static HRESULT WINAPI NullRenderer_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
+HRESULT NullRenderer_create(IUnknown *pUnkOuter, void **ppv)
{
- NullRendererImpl *This = (NullRendererImpl *)iface;
-
- TRACE("(%p/%p)->(%p)\n", This, iface, pInfo);
+ HRESULT hr;
+ NullRendererImpl *pNullRenderer;
- strcpyW(pInfo->achName, This->filterInfo.achName);
- pInfo->pGraph = This->filterInfo.pGraph;
+ TRACE("(%p, %p)\n", pUnkOuter, ppv);
- if (pInfo->pGraph)
- IFilterGraph_AddRef(pInfo->pGraph);
+ *ppv = NULL;
- return S_OK;
-}
+ pNullRenderer = CoTaskMemAlloc(sizeof(NullRendererImpl));
+ pNullRenderer->IUnknown_inner.lpVtbl = &IInner_VTable;
+ pNullRenderer->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_Vtbl;
-static HRESULT WINAPI NullRenderer_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName)
-{
- NullRendererImpl *This = (NullRendererImpl *)iface;
+ if (pUnkOuter)
+ pNullRenderer->outer_unk = pUnkOuter;
+ else
+ pNullRenderer->outer_unk = &pNullRenderer->IUnknown_inner;
- TRACE("(%p/%p)->(%p, %s)\n", This, iface, pGraph, debugstr_w(pName));
+ hr = BaseRenderer_Init(&pNullRenderer->renderer, &NullRenderer_Vtbl, pUnkOuter,
+ &CLSID_NullRenderer, (DWORD_PTR)(__FILE__ ": NullRendererImpl.csFilter"),
+ &RendererFuncTable);
- EnterCriticalSection(&This->csFilter);
+ if (FAILED(hr))
{
- if (pName)
- strcpyW(This->filterInfo.achName, pName);
- else
- *This->filterInfo.achName = '\0';
- This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
+ BaseRendererImpl_Release(&pNullRenderer->renderer.filter.IBaseFilter_iface);
+ CoTaskMemFree(pNullRenderer);
}
- LeaveCriticalSection(&This->csFilter);
+ else
+ *ppv = &pNullRenderer->IUnknown_inner;
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;
-}
-
-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
-};
-
-static HRESULT WINAPI NullRenderer_InputPin_EndOfStream(IPin * 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;
-}
-
-static const IPinVtbl NullRenderer_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,
- NullRenderer_InputPin_EndOfStream,
- InputPin_BeginFlush,
- InputPin_EndFlush,
- InputPin_NewSegment
-};
*/
#include "quartz_private.h"
-#include "control_private.h"
#include "pin.h"
//#include "vfwmsgs.h"
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);
+}
+
+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];
+}
-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 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;
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);
}
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))
- *ppv = This;
- else if (IsEqualIID(riid, &IID_IPersist))
+ if ( IsEqualIID(riid, &IID_IUnknown)
+ || IsEqualIID(riid, &IID_IPersist)
+ || IsEqualIID(riid, &IID_IMediaFilter)
+ || IsEqualIID(riid, &IID_IBaseFilter) )
*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)
{
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)
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 */
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);
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);
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;
}
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");
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);
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;
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;
}
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;
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;
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;
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)
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;
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
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;
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);
*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)
{
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);
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);
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");
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);
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;
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,
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);
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);
+}
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))
* 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;
}
out:
+ if (enumpins)
+ IEnumPins_Release( enumpins );
if (pin_info.pFilter)
IBaseFilter_Release( pin_info.pFilter );
return hr;
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;
- 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 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)
+static HRESULT deliver_endofstream(IPin* pin, LPVOID unused)
{
- 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;
+ return IPin_EndOfStream( pin );
}
-HRESULT OutputPin_SendSample(OutputPin * This, IMediaSample * pSample)
+static HRESULT deliver_beginflush(IPin* pin, LPVOID unused)
{
- 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;
+ return IPin_BeginFlush( pin );
}
-HRESULT OutputPin_CommitAllocator(OutputPin * This)
+static HRESULT deliver_endflush(IPin* pin, LPVOID unused)
{
- 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;
+ return IPin_EndFlush( pin );
}
-HRESULT OutputPin_DecommitAllocator(OutputPin * This)
+typedef struct newsegmentargs
{
- 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;
-}
+ REFERENCE_TIME tStart, tStop;
+ double rate;
+} newsegmentargs;
-HRESULT OutputPin_DeliverDisconnect(OutputPin * This)
+static HRESULT deliver_newsegment(IPin *pin, LPVOID data)
{
- 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;
+ newsegmentargs *args = data;
+ return IPin_NewSegment(pin, args->tStart, args->tStop, args->rate);
}
/*** PullPin implementation ***/
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);
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;
}
{
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);
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? */
This->pReader = NULL;
This->pAlloc = NULL;
+ This->prefAlloc = NULL;
if (SUCCEEDED(hr))
{
hr = IPin_QueryInterface(pReceivePin, &IID_IAsyncReader, (LPVOID *)&This->pReader);
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 = StdMemAllocator_create(NULL, (LPVOID *) &This->prefAlloc);
+ }
+
if (SUCCEEDED(hr))
{
- hr = IAsyncReader_RequestAllocator(This->pReader, NULL, &props, &This->pAlloc);
+ hr = IAsyncReader_RequestAllocator(This->pReader, This->prefAlloc, &props, &This->pAlloc);
}
if (SUCCEEDED(hr))
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;
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);
*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)
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);
WaitForSingleObject(This->hEventStateChanged, INFINITE);
assert(!This->hThread);
+ if(This->prefAlloc)
+ IMemAllocator_Release(This->prefAlloc);
if(This->pAlloc)
IMemAllocator_Release(This->pAlloc);
if(This->pReader)
if (This->pReader)
{
+ /* Do not allow state to change while flushing */
+ EnterCriticalSection(This->pin.pCritSec);
+
/* Flush outstanding samples */
IAsyncReader_BeginFlush(This->pReader);
}
IAsyncReader_EndFlush(This->pReader);
+
+ LeaveCriticalSection(This->pin.pCritSec);
}
}
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);
/* 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)
}
} 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);
}
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);
}
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;
+
+ TRACE("(%p)->()\n", iface);
+
+ EnterCriticalSection(This->pin.pCritSec);
+ hr = SendFurther( iface, deliver_endofstream, NULL, NULL );
+ SetEvent(This->hEventStateChanged);
+ LeaveCriticalSection(This->pin.pCritSec);
- return SendFurther( iface, deliver_endofstream, NULL, NULL );
+ 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);
EnterCriticalSection(This->pin.pCritSec);
{
- This->fnCleanProc(This->pin.pUserData);
+ This->fnCleanProc(This->pUserData);
}
LeaveCriticalSection(This->pin.pCritSec);
HRESULT WINAPI PullPin_EndFlush(IPin * iface)
{
- PullPin *This = (PullPin *)iface;
+ PullPin *This = impl_PullPin_from_IPin(iface);
TRACE("(%p)->()\n", iface);
HRESULT WINAPI PullPin_Disconnect(IPin *iface)
{
HRESULT hr;
- PullPin *This = (PullPin *)iface;
+ PullPin *This = impl_PullPin_from_IPin(iface);
TRACE("()\n");
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;
-}
* 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.
#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;
#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);
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);
+}
*
* 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
#include <objbase.h>
#include <oleauto.h>
#include <dshow.h>
+#include <wine/strmbase.h>
#include <wine/list.h>
#define MEDIATIME_FROM_BYTES(x) ((LONGLONG)(x) * 10000000)
#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);
-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);
-
-typedef struct tagENUMEDIADETAILS
-{
- ULONG cMediaTypes;
- AM_MEDIA_TYPE * pMediaTypes;
-} ENUMMEDIADETAILS;
+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 EnumMonikerImpl_Create(IMoniker ** ppMoniker, ULONG nMonikerCount, IEnumMoniker ** ppEnum) DECLSPEC_HIDDEN;
+
+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;
+
+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 );
-
-typedef struct StdMediaSample2
-{
- const IMediaSample2Vtbl * lpvtbl;
+void dump_AM_MEDIA_TYPE(const AM_MEDIA_TYPE * pmt) DECLSPEC_HIDDEN;
- 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__ */
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-/* just a wrapper for strmif.idl */
-
cpp_quote("#include <wingdi.h>")
#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; }
--- /dev/null
+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' }
+ }
+ }
+}
/***********************************************************************
* 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 };
/***********************************************************************
}
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,
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;
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 */
};
{ &CLSID_AviSplitter,
&CLSID_LegacyAmFilterCategory,
{'A','V','I',' ','S','p','l','i','t','t','e','r',0},
- 0x600000,
+ 0x5ffff0,
{ { 0,
{ { &MEDIATYPE_Stream, &MEDIASUBTYPE_Avi },
{ NULL }
{ &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 },
{ 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},
{ &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 }
{ &CLSID_ACMWrapper,
&CLSID_LegacyAmFilterCategory,
{'A','C','M',' ','W','r','a','p','p','e','r',0},
- 0x600000,
+ 0x5ffff0,
{ { 0,
{ { &MEDIATYPE_Audio, &GUID_NULL },
{ NULL }
};
typedef struct SystemClockImpl {
- const IReferenceClockVtbl *lpVtbl;
+ IReferenceClock IReferenceClock_iface;
LONG ref;
/** IReferenceClock */
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;
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;
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:
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);
}
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);
}
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) ||
}
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) {
}
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;
}
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),
}
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),
}
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;
}
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);
}
+++ /dev/null
-/*
- * 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 <config.h>
-
-#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 <assert.h>
-
-#include <wine/unicode.h>
-#include <wine/debug.h>
-
-#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
-};
+++ /dev/null
-/*
- * 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);
* 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
#define NONAMELESSSTRUCT
#define NONAMELESSUNION
#include "quartz_private.h"
-#include "control_private.h"
#include "pin.h"
//#include "uuids.h"
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;
-
- LONG refCount;
- CRITICAL_SECTION csFilter;
- FILTER_STATE state;
- REFERENCE_TIME rtStreamStart;
- IReferenceClock * pClock;
- FILTER_INFO filterInfo;
+ BaseRenderer renderer;
+ BaseControlWindow baseControlWindow;
+ BaseControlVideo baseControlVideo;
- 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;
-
- 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";
-
- if (!wnd_class_registered)
- {
- if (!RegisterClassA(&winclass))
- {
- ERR("Unable to register window %u\n", GetLastError());
- return FALSE;
- }
- wnd_class_registered = TRUE;
- }
+ return CONTAINING_RECORD(iface, VideoRendererImpl, renderer);
+}
- 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_IBaseFilter(IBaseFilter *iface)
+{
+ return CONTAINING_RECORD(iface, VideoRendererImpl, renderer.filter.IBaseFilter_iface);
+}
- if (!This->hWnd)
- {
- ERR("Unable to create window\n");
- return FALSE;
- }
+static inline VideoRendererImpl *impl_from_IVideoWindow(IVideoWindow *iface)
+{
+ return CONTAINING_RECORD(iface, VideoRendererImpl, baseControlWindow.IVideoWindow_iface);
+}
- SetWindowLongPtrW(This->hWnd, 0, (LONG_PTR)This);
+static inline VideoRendererImpl *impl_from_BaseControlVideo(BaseControlVideo *iface)
+{
+ return CONTAINING_RECORD(iface, VideoRendererImpl, baseControlVideo);
+}
- return TRUE;
+static inline VideoRendererImpl *impl_from_IBasicVideo(IBasicVideo *iface)
+{
+ return CONTAINING_RECORD(iface, VideoRendererImpl, baseControlVideo.IBasicVideo_iface);
}
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);
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");
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;
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;
}
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;
+ /* 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 VideoRenderer_DoRenderSample(BaseRenderer* iface, IMediaSample * pSample)
+{
+ VideoRendererImpl *This = impl_from_BaseRenderer(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;
- }
+ 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;
}
#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 <SHOULD> 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;
IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB565) ||
IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_RGB8))
{
- VideoRendererImpl* This = iface;
LONG height;
if (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo))
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);
+
+ TRACE("(%p)->()\n", This);
- return IUnknown_QueryInterface((IUnknown *)This, riid, ppv);
+ 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;
-static HRESULT VideoRendererImpl_Change(IBaseFilter *iface)
-{
- TRACE("(%p)->()\n", iface);
- return S_OK;
+ defRect.left = defRect.top = 0;
+ defRect.right = This->VideoWidth;
+ defRect.bottom = This->VideoHeight;
+
+ return defRect;
}
-HRESULT VideoRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv)
+static BOOL WINAPI VideoRenderer_OnSize(BaseWindow *iface, LONG Width, LONG Height)
{
- HRESULT hr;
- PIN_INFO piInput;
- VideoRendererImpl * pVideoRenderer;
+ 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,
+};
- TRACE("(%p, %p)\n", pUnkOuter, ppv);
+static const BaseWindowFuncTable renderer_BaseWindowFuncTable = {
+ VideoRenderer_GetClassWindowStyles,
+ VideoRenderer_GetDefaultRect,
+ NULL,
+ BaseControlWindowImpl_PossiblyEatMessage,
+ VideoRenderer_OnSize
+};
- *ppv = NULL;
+static HRESULT WINAPI VideoRenderer_GetSourceRect(BaseControlVideo* iface, RECT *pSourceRect)
+{
+ VideoRendererImpl *This = impl_from_BaseControlVideo(iface);
+ CopyRect(pSourceRect,&This->SourceRect);
+ return S_OK;
+}
- 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;
+static HRESULT WINAPI VideoRenderer_GetStaticImage(BaseControlVideo* iface, LONG *pBufferSize, LONG *pDIBImage)
+{
+ VideoRendererImpl *This = impl_from_BaseControlVideo(iface);
+ BITMAPINFOHEADER *bmiHeader;
+ LONG needed_size;
+ AM_MEDIA_TYPE *amt = &This->renderer.pInputPin->pin.mtCurrent;
+ char *ptr;
- /* construct input pin */
- piInput.dir = PINDIR_INPUT;
- piInput.pFilter = (IBaseFilter *)pVideoRenderer;
- lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
+ FIXME("(%p/%p)->(%p, %p): partial stub\n", This, iface, pBufferSize, pDIBImage);
- hr = InputPin_Construct(&VideoRenderer_InputPin_Vtbl, &piInput, VideoRenderer_Sample, (LPVOID)pVideoRenderer, VideoRenderer_QueryAccept, NULL, &pVideoRenderer->csFilter, NULL, (IPin **)&pVideoRenderer->pInputPin);
+ EnterCriticalSection(&This->renderer.filter.csFilter);
- 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))
- return E_FAIL;
+ needed_size = bmiHeader->biSize;
+ needed_size += IMediaSample_GetActualDataLength(This->renderer.pMediaSample);
- pVideoRenderer->blocked = CreateEventW(NULL, FALSE, FALSE, NULL);
- if (!pVideoRenderer->blocked)
+ if (!pDIBImage)
{
- hr = HRESULT_FROM_WIN32(GetLastError());
- IUnknown_Release((IUnknown *)pVideoRenderer);
+ *pBufferSize = needed_size;
+ LeaveCriticalSection(&This->renderer.filter.csFilter);
+ return S_OK;
}
- return hr;
+ 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;
}
-HRESULT VideoRendererDefault_create(IUnknown * pUnkOuter, LPVOID * ppv)
+static HRESULT WINAPI VideoRenderer_GetTargetRect(BaseControlVideo* iface, RECT *pTargetRect)
{
- /* TODO: Attempt to use the VMR-7 renderer instead when possible */
- return VideoRenderer_create(pUnkOuter, ppv);
+ VideoRendererImpl *This = impl_from_BaseControlVideo(iface);
+ CopyRect(pTargetRect,&This->DestRect);
+ return S_OK;
}
-static HRESULT WINAPI VideoRendererInner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv)
+static VIDEOINFOHEADER* WINAPI VideoRenderer_GetVideoFormat(BaseControlVideo* iface)
{
- ICOM_THIS_MULTI(VideoRendererImpl, IInner_vtbl, iface);
- TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
+ 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);
- if (This->bAggregatable)
- This->bUnkOuterValid = TRUE;
+ 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;
+
+ This->DestRect.left = 0;
+ This->DestRect.top = 0;
+ This->DestRect.right = rect.right;
+ This->DestRect.bottom = rect.bottom;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI VideoRenderer_SetSourceRect(BaseControlVideo* iface, RECT *pSourceRect)
+{
+ VideoRendererImpl *This = impl_from_BaseControlVideo(iface);
+ CopyRect(&This->SourceRect,pSourceRect);
+ return S_OK;
+}
+
+static HRESULT WINAPI VideoRenderer_SetTargetRect(BaseControlVideo* iface, RECT *pTargetRect)
+{
+ 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);
*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;
}
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
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));
+ VideoRendererImpl *This = impl_from_IBaseFilter(iface);
+ return IUnknown_Release(This->outer_unk);
}
-/** IPersist methods **/
+/** IMediaFilter methods **/
-static HRESULT WINAPI VideoRenderer_GetClassID(IBaseFilter * iface, CLSID * pClsid)
+static HRESULT WINAPI VideoRenderer_Pause(IBaseFilter * iface)
{
- VideoRendererImpl *This = (VideoRendererImpl *)iface;
-
- TRACE("(%p/%p)->(%p)\n", This, iface, pClsid);
+ VideoRendererImpl *This = impl_from_IBaseFilter(iface);
- *pClsid = CLSID_VideoRenderer;
+ TRACE("(%p/%p)->()\n", This, iface);
- return S_OK;
-}
-
-/** 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;
-
- TRACE("(%p/%p)->()\n", This, iface);
-
- EnterCriticalSection(&This->csFilter);
- if (This->state != State_Paused)
- {
- if (This->state == State_Stopped)
- {
- This->pInputPin->end_of_stream = 0;
- ResetEvent(This->hEvent);
- }
-
- This->state = State_Paused;
- ResetEvent(This->blocked);
- }
- LeaveCriticalSection(&This->csFilter);
-
- 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)
+ 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);
}
- 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 */
+ ResetEvent(This->renderer.RenderEvent);
+ This->renderer.filter.state = State_Paused;
}
- LeaveCriticalSection(&This->csFilter);
+ LeaveCriticalSection(&This->renderer.csRenderLock);
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
+ BaseRendererImpl_Run,
+ BaseRendererImpl_GetState,
+ BaseRendererImpl_SetSyncSource,
+ BaseFilterImpl_GetSyncSource,
+ BaseFilterImpl_EnumPins,
+ BaseRendererImpl_FindPin,
+ BaseFilterImpl_QueryFilterInfo,
+ BaseFilterImpl_JoinFilterGraph,
+ BaseFilterImpl_QueryVendorInfo
};
-static HRESULT WINAPI VideoRenderer_InputPin_EndOfStream(IPin * iface)
+/*** IUnknown methods ***/
+static HRESULT WINAPI BasicVideo_QueryInterface(IBasicVideo *iface, REFIID riid, LPVOID *ppvObj)
{
- InputPin* This = (InputPin*)iface;
- IMediaEventSink* pEventSink;
- HRESULT hr;
-
- TRACE("(%p/%p)->()\n", This, iface);
+ VideoRendererImpl *This = impl_from_IBasicVideo(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);
- }
+ TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
- return hr;
+ return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
}
-static HRESULT WINAPI VideoRenderer_InputPin_BeginFlush(IPin * iface)
+static ULONG WINAPI BasicVideo_AddRef(IBasicVideo *iface)
{
- InputPin* This = (InputPin*)iface;
- VideoRendererImpl *pVideoRenderer = (VideoRendererImpl *)This->pin.pinInfo.pFilter;
- HRESULT hr;
+ VideoRendererImpl *This = impl_from_IBasicVideo(iface);
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;
+ return IUnknown_AddRef(This->outer_unk);
}
-static HRESULT WINAPI VideoRenderer_InputPin_EndFlush(IPin * iface)
+static ULONG WINAPI BasicVideo_Release(IBasicVideo *iface)
{
- InputPin* This = (InputPin*)iface;
- VideoRendererImpl *pVideoRenderer = (VideoRendererImpl *)This->pin.pinInfo.pFilter;
- HRESULT hr;
+ VideoRendererImpl *This = impl_from_IBasicVideo(iface);
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;
+ return IUnknown_Release(This->outer_unk);
}
-static const IPinVtbl VideoRenderer_InputPin_Vtbl =
+static const IBasicVideoVtbl IBasicVideo_VTable =
{
- 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
+ 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 Basicvideo_QueryInterface(IBasicVideo *iface,
- REFIID riid,
- LPVOID*ppvObj) {
- ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_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 Basicvideo_AddRef(IBasicVideo *iface) {
- ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_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 Basicvideo_Release(IBasicVideo *iface) {
- ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_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);
-}
-
-/*** 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;
+ return IUnknown_Release(This->outer_unk);
}
-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);
+static HRESULT WINAPI VideoWindow_get_FullScreenMode(IVideoWindow *iface,
+ LONG *FullScreenMode)
+{
+ VideoRendererImpl *This = impl_from_IVideoWindow(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);
+ FIXME("(%p/%p)->(%p): stub !!!\n", This, iface, FullScreenMode);
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;
+static HRESULT WINAPI VideoWindow_put_FullScreenMode(IVideoWindow *iface,
+ LONG FullScreenMode)
+{
+ VideoRendererImpl *This = impl_from_IVideoWindow(iface);
- TRACE("(%p/%p)->(%p)\n", This, iface, pAvgTimePerFrame);
+ FIXME("(%p/%p)->(%d): stub !!!\n", This, iface, FullScreenMode);
- 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;
+ 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 {
- ERR("Unknown format type %s\n", qzdebugstr_guid(&pmt->formattype));
- *pAvgTimePerFrame = 0;
+ 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 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;
+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,
+ VideoWindow_get_FullScreenMode,
+ VideoWindow_put_FullScreenMode,
+ BaseControlWindowImpl_SetWindowForeground,
+ BaseControlWindowImpl_NotifyOwnerMessage,
+ BaseControlWindowImpl_SetWindowPosition,
+ BaseControlWindowImpl_GetWindowPosition,
+ BaseControlWindowImpl_GetMinIdealImageSize,
+ BaseControlWindowImpl_GetMaxIdealImageSize,
+ BaseControlWindowImpl_GetRestorePosition,
+ BaseControlWindowImpl_HideCursor,
+ BaseControlWindowImpl_IsCursorHidden
+};
- return S_OK;
+static VideoRendererImpl *impl_from_IAMFilterMiscFlags(IAMFilterMiscFlags *iface)
+{
+ return CONTAINING_RECORD(iface, VideoRendererImpl, IAMFilterMiscFlags_iface);
}
-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 AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid,
+ void **ppv)
+{
+ VideoRendererImpl *This = impl_from_IAMFilterMiscFlags(iface);
+ return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
}
-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 ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface)
+{
+ VideoRendererImpl *This = impl_from_IAMFilterMiscFlags(iface);
+ return IUnknown_AddRef(This->outer_unk);
}
-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 ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface)
+{
+ VideoRendererImpl *This = impl_from_IAMFilterMiscFlags(iface);
+ return IUnknown_Release(This->outer_unk);
}
-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 ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface)
+{
+ return AM_FILTER_MISC_FLAGS_IS_RENDERER;
}
-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;
+static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = {
+ AMFilterMiscFlags_QueryInterface,
+ AMFilterMiscFlags_AddRef,
+ AMFilterMiscFlags_Release,
+ AMFilterMiscFlags_GetMiscFlags
+};
- return S_OK;
-}
+HRESULT VideoRenderer_create(IUnknown *pUnkOuter, void **ppv)
+{
+ HRESULT hr;
+ VideoRendererImpl * pVideoRenderer;
-static HRESULT WINAPI Basicvideo_put_DestinationWidth(IBasicVideo *iface,
- LONG DestinationWidth) {
- ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+ TRACE("(%p, %p)\n", pUnkOuter, ppv);
- TRACE("(%p/%p)->(%d)\n", This, iface, DestinationWidth);
+ *ppv = NULL;
- This->DestRect.right = This->DestRect.left + DestinationWidth;
+ pVideoRenderer = CoTaskMemAlloc(sizeof(VideoRendererImpl));
+ pVideoRenderer->IUnknown_inner.lpVtbl = &IInner_VTable;
+ pVideoRenderer->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_Vtbl;
- return S_OK;
-}
+ pVideoRenderer->init = 0;
+ ZeroMemory(&pVideoRenderer->SourceRect, sizeof(RECT));
+ ZeroMemory(&pVideoRenderer->DestRect, sizeof(RECT));
+ ZeroMemory(&pVideoRenderer->WindowPos, sizeof(RECT));
-static HRESULT WINAPI Basicvideo_get_DestinationWidth(IBasicVideo *iface,
- LONG *pDestinationWidth) {
- ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+ if (pUnkOuter)
+ pVideoRenderer->outer_unk = pUnkOuter;
+ else
+ pVideoRenderer->outer_unk = &pVideoRenderer->IUnknown_inner;
- TRACE("(%p/%p)->(%p)\n", This, iface, pDestinationWidth);
+ hr = BaseRenderer_Init(&pVideoRenderer->renderer, &VideoRenderer_Vtbl, pUnkOuter,
+ &CLSID_VideoRenderer, (DWORD_PTR)(__FILE__ ": VideoRendererImpl.csFilter"),
+ &BaseFuncTable);
- *pDestinationWidth = This->DestRect.right - This->DestRect.left;
+ if (FAILED(hr))
+ goto fail;
- return S_OK;
-}
+ 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;
-static HRESULT WINAPI Basicvideo_put_DestinationTop(IBasicVideo *iface,
- LONG DestinationTop) {
- ICOM_THIS_MULTI(VideoRendererImpl, IBasicVideo_vtbl, iface);
+ 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;
- TRACE("(%p/%p)->(%d)\n", This, iface, DestinationTop);
+ if (!CreateRenderingSubsystem(pVideoRenderer)) {
+ hr = E_FAIL;
+ goto fail;
+ }
- This->DestRect.top = DestinationTop;
-
+ *ppv = &pVideoRenderer->IUnknown_inner;
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;
+fail:
+ BaseRendererImpl_Release(&pVideoRenderer->renderer.filter.IBaseFilter_iface);
+ CoTaskMemFree(pVideoRenderer);
+ return hr;
}
-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;
+HRESULT VideoRendererDefault_create(IUnknown * pUnkOuter, LPVOID * ppv)
+{
+ /* TODO: Attempt to use the VMR-7 renderer instead when possible */
+ return VideoRenderer_create(pUnkOuter, ppv);
}
-
-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
-};
-
-
-/*** IUnknown methods ***/
-static HRESULT WINAPI Videowindow_QueryInterface(IVideoWindow *iface,
- REFIID riid,
- LPVOID*ppvObj) {
- ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
-
- TRACE("(%p/%p)->(%s (%p), %p)\n", This, iface, debugstr_guid(riid), riid, ppvObj);
-
- return VideoRenderer_QueryInterface((IBaseFilter*)This, riid, ppvObj);
-}
-
-static ULONG WINAPI Videowindow_AddRef(IVideoWindow *iface) {
- ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
-
- TRACE("(%p/%p)->()\n", This, iface);
-
- return VideoRenderer_AddRef((IBaseFilter*)This);
-}
-
-static ULONG WINAPI Videowindow_Release(IVideoWindow *iface) {
- ICOM_THIS_MULTI(VideoRendererImpl, IVideoWindow_vtbl, iface);
-
- TRACE("(%p/%p)->()\n", This, iface);
-
- return VideoRenderer_Release((IBaseFilter*)This);
-}
-
-/*** 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);
-
- 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);
-
- 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);
-
- 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
-};
--- /dev/null
+/*
+ * 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;
+}
*/
#include "quartz_private.h"
-#include "control_private.h"
#include "pin.h"
//#include "uuids.h"
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);
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);
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)
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;
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);
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)
{
}
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;
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);
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;
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));
mmstream.idl
qedit.idl
regbag.idl
- strmif.idl
tvratings.idl
vidcap.idl
videoacc.idl
interface IAMVideoCompression;
interface IAMVideoDecimationProperties;
interface IAMVideoProcAmp;
+interface IAMGraphBuilderCallback;
interface ICaptureGraphBuilder;
interface ICaptureGraphBuilder2;
interface IConfigAviMux;
{
ULONG cPins;
[size_is(cPins)] const REGFILTERPINS *rgPins;
- } DUMMYSTRUCTNAME;
+ } DUMMYSTRUCTNAME1;
[case(2)]
struct
{
ULONG cPins2;
[size_is(cPins2)] const REGFILTERPINS2 *rgPins2;
- } DUMMYSTRUCTNAME1;
+ } DUMMYSTRUCTNAME2;
[default]
;
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,
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)
-]
-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 );
-}
-
-
-/*****************************************************************************
- * 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();
-}
-
-[
- uuid(329bb360-f6ea-11d1-9038-00a0c9697298),
- helpstring("IBasicVideo2"),
- odl
-]
-
-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 );
-}
-
-
-/*****************************************************************************
- * 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)
+ version(1.0),
+ uuid(56a868b0-0ad4-11ce-b03a-0020af0ba770)
]
-interface IMediaPosition : IDispatch
+library QuartzTypeLib
{
- 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 );
-}
+ 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 );
+ }
+
+
+ /***************************************************************************
+ * 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();
+ }
+
+ [
+ uuid(329bb360-f6ea-11d1-9038-00a0c9697298),
+ helpstring("IBasicVideo2"),
+ odl
+ ]
+
+ 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 );
+ }
+
+
+ /***************************************************************************
+ * 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 );
+ }
+
+} /* library QuartzTypeLib */
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+import "unknwn.idl";
import "objidl.idl";
#include <devenum.idl>
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;
--- /dev/null
+/*
+ * 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);
add_subdirectory(libwine)
add_subdirectory(libxml2)
# add_subdirectory(stlport) FIXME: Add proper STL support
+add_subdirectory(strmbase)
add_subdirectory(zlib)
--- /dev/null
+
+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)
--- /dev/null
+/*
+ * 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 <assert.h>
+#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;
+}
--- /dev/null
+/*
+ * 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 <assert.h>
+
+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;
+}
--- /dev/null
+/*
+ * 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 <stdarg.h>
+#include <assert.h>
+
+#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;
+}
* 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
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#include "quartz_private.h"
+#define COBJMACROS
-#include <wine/debug.h>
+#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;
*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;
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;
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);
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;
}
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;
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);
-
- if (hr == S_OK)
- ++i;
-
- if (synctime != This->synctime)
- break;
+ IPin *pin;
+ pin = This->receive_pin(This->base, This->uIndex + i);
+
+ 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;
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;
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);
--- /dev/null
+/*
+ * 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 <assert.h>
+
+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;
+}
--- /dev/null
+/*
+ * 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 <stdarg.h>
+
+#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
+};
--- /dev/null
+/*
+ * 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 <assert.h>
+
+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;
+}
--- /dev/null
+/*
+ * 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 <assert.h>
+
+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;
+}
--- /dev/null
+/*
+ * 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 <assert.h>
+
+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
+};
--- /dev/null
+/*
+ * 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 <wim.taymans@gmail.com>
+ *
+ * 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 <assert.h>
+
+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);
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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 <assert.h>
+
+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;
+}
--- /dev/null
+/*
+ * 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);
--- /dev/null
+/*
+ * 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 <stdarg.h>
+
+#define COBJMACROS
+
+#include "windef.h"
+#include "winbase.h"
+#include "dshow.h"
+#include "amvideo.h"
+#include "strmif.h"
+#include "vfw.h"
+
+#include <assert.h>
+
+#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
+};
--- /dev/null
+/*
+ * 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 <assert.h>
+#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);
+}
--- /dev/null
+/*
+ * 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 <assert.h>
+
+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;
+}
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
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