* 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
This commit is contained in:
Amine Khaldi 2013-06-20 12:07:29 +00:00
parent 8eccf8f3b5
commit 1d814c38a6
63 changed files with 15274 additions and 9246 deletions

View file

@ -202,8 +202,8 @@ else()
include/psdk
include/dxsdk
${REACTOS_BINARY_DIR}/include
${REACTOS_BINARY_DIR}/include/dxsdk
${REACTOS_BINARY_DIR}/include/psdk
${REACTOS_BINARY_DIR}/include/dxsdk
${REACTOS_BINARY_DIR}/include/reactos
include/crt
include/ddk

View file

@ -258,7 +258,7 @@ static void DEVENUM_ReadPins(HKEY hkeyFilterClass, REGFILTER2 *rgf2)
WCHAR wszPinName[MAX_PATH];
DWORD cName = sizeof(wszPinName) / sizeof(WCHAR);
DWORD Type, cbData;
REGFILTERPINS *rgPin = &rgPins[rgf2->u.s.cPins];
REGFILTERPINS *rgPin = &rgPins[rgf2->u.s1.cPins];
LONG lRet;
rgPin->strName = NULL;
@ -298,7 +298,7 @@ static void DEVENUM_ReadPins(HKEY hkeyFilterClass, REGFILTER2 *rgf2)
DEVENUM_ReadPinTypes(hkeyPinKey, rgPin);
++rgf2->u.s.cPins;
++rgf2->u.s1.cPins;
continue;
error_cleanup:
@ -309,13 +309,13 @@ static void DEVENUM_ReadPins(HKEY hkeyFilterClass, REGFILTER2 *rgf2)
RegCloseKey(hkeyPins);
if (rgPins && !rgf2->u.s.cPins)
if (rgPins && !rgf2->u.s1.cPins)
{
CoTaskMemFree(rgPins);
rgPins = NULL;
}
rgf2->u.s.rgPins = rgPins;
rgf2->u.s1.rgPins = rgPins;
}
static HRESULT DEVENUM_RegisterLegacyAmFilters(void)
@ -387,8 +387,8 @@ static HRESULT DEVENUM_RegisterLegacyAmFilters(void)
rgf2.dwVersion = 1;
rgf2.dwMerit = 0;
rgf2.u.s.cPins = 0;
rgf2.u.s.rgPins = NULL;
rgf2.u.s1.cPins = 0;
rgf2.u.s1.rgPins = NULL;
cbData = sizeof(wszFilterName);
if (RegQueryValueExW(hkeyFilterClass, NULL, NULL, &Type, (LPBYTE)wszFilterName, &cbData) != ERROR_SUCCESS ||
@ -414,29 +414,29 @@ static HRESULT DEVENUM_RegisterLegacyAmFilters(void)
if (hkeyFilterClass) RegCloseKey(hkeyFilterClass);
if (rgf2.u.s.rgPins)
if (rgf2.u.s1.rgPins)
{
UINT iPin;
for (iPin = 0; iPin < rgf2.u.s.cPins; iPin++)
for (iPin = 0; iPin < rgf2.u.s1.cPins; iPin++)
{
CoTaskMemFree(rgf2.u.s.rgPins[iPin].strName);
CoTaskMemFree(rgf2.u.s1.rgPins[iPin].strName);
if (rgf2.u.s.rgPins[iPin].lpMediaType)
if (rgf2.u.s1.rgPins[iPin].lpMediaType)
{
UINT iType;
for (iType = 0; iType < rgf2.u.s.rgPins[iPin].nMediaTypes; iType++)
for (iType = 0; iType < rgf2.u.s1.rgPins[iPin].nMediaTypes; iType++)
{
CoTaskMemFree((void*)rgf2.u.s.rgPins[iPin].lpMediaType[iType].clsMajorType);
CoTaskMemFree((void*)rgf2.u.s.rgPins[iPin].lpMediaType[iType].clsMinorType);
CoTaskMemFree((void*)rgf2.u.s1.rgPins[iPin].lpMediaType[iType].clsMajorType);
CoTaskMemFree((void*)rgf2.u.s1.rgPins[iPin].lpMediaType[iType].clsMinorType);
}
CoTaskMemFree((void*)rgf2.u.s.rgPins[iPin].lpMediaType);
CoTaskMemFree((void*)rgf2.u.s1.rgPins[iPin].lpMediaType);
}
}
CoTaskMemFree((void*)rgf2.u.s.rgPins);
CoTaskMemFree((void*)rgf2.u.s1.rgPins);
}
}
}
@ -606,8 +606,8 @@ static HRESULT DEVENUM_CreateSpecialCategories(void)
rf2.dwVersion = 2;
rf2.dwMerit = MERIT_PREFERRED;
rf2.u.s1.cPins2 = 1;
rf2.u.s1.rgPins2 = &rfp2;
rf2.u.s2.cPins2 = 1;
rf2.u.s2.rgPins2 = &rfp2;
rfp2.cInstances = 1;
rfp2.nMediums = 0;
rfp2.lpMedium = NULL;

View file

@ -5,49 +5,57 @@ add_definitions(-D_WIN32_WINNT=0x600)
add_definitions(
-D__WINESRC__
-DENTRY_PREFIX=QUARTZ_
-DREGISTER_PROXY_DLL
-DWINE_REGISTER_DLL
-DPROXY_DELEGATION)
include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine)
spec2def(quartz.dll quartz.spec)
add_rpcproxy_files(quartz_strmif.idl)
list(APPEND SOURCE
avidec.c
acmwrapper.c
waveparser.c
videorenderer.c
transform.c
systemclock.c
regsvr.c
pin.c
parser.c
nullrenderer.c
mpegsplit.c
memallocator.c
main.c
filtermapper.c
filtergraph.c
filesource.c
enumregfilters.c
enumpins.c
enummoniker.c
enumfilters.c
dsoundrender.c
enummedia.c
control.c
avidec.c
avisplit.c
dsoundrender.c
enumfilters.c
enummedia.c
enummoniker.c
enumregfilters.c
filesource.c
filtergraph.c
filtermapper.c
main.c
memallocator.c
mpegsplit.c
nullrenderer.c
parser.c
pin.c
regsvr.c
systemclock.c
videorenderer.c
vmr9.c
waveparser.c
${CMAKE_CURRENT_BINARY_DIR}/proxy.dlldata.c
${CMAKE_CURRENT_BINARY_DIR}/quartz_strmif_p.c
${CMAKE_CURRENT_BINARY_DIR}/quartz.def)
add_library(quartz SHARED ${SOURCE} version.rc)
add_idl_headers(quartz_idlheader fil_data.idl)
add_typelib(control_tlb.idl)
list(APPEND quartz_rc_deps
${CMAKE_CURRENT_BINARY_DIR}/control_tlb.tlb
${CMAKE_CURRENT_SOURCE_DIR}/control_tlb.rgs
${CMAKE_CURRENT_SOURCE_DIR}/quartz_strmif.rgs)
set_source_files_properties(version.rc PROPERTIES OBJECT_DEPENDS "${quartz_rc_deps}")
set_module_type(quartz win32dll)
target_link_libraries(quartz strmiids uuid wine ${PSEH_LIB})
add_importlibs(quartz dsound ole32 oleaut32 shlwapi user32 gdi32 advapi32 msvfw32 msacm32 rpcrt4 msvcrt kernel32 ntdll)
add_dependencies(quartz dxsdk)
target_link_libraries(quartz strmbase strmiids uuid dxguid wine ${PSEH_LIB})
add_importlibs(quartz dsound msacm32 msvfw32 ole32 oleaut32 shlwapi rpcrt4 user32 gdi32 advapi32 msvcrt kernel32 ntdll)
add_dependencies(quartz dxsdk quartz_idlheader stdole2)
add_pch(quartz quartz_private.h)
add_cd_file(TARGET quartz DESTINATION reactos/system32 FOR all)

View file

@ -37,13 +37,12 @@
//#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;
@ -52,9 +51,21 @@ typedef struct ACMWrapperImpl
LONGLONG lasttime_sent;
} ACMWrapperImpl;
static HRESULT ACMWrapper_ProcessSampleData(InputPin *pin, IMediaSample *pSample)
static const IBaseFilterVtbl ACMWrapper_Vtbl;
static inline ACMWrapperImpl *impl_from_TransformFilter( TransformFilter *iface )
{
ACMWrapperImpl* This = (ACMWrapperImpl*)pin->pin.pinInfo.pFilter;
return CONTAINING_RECORD(iface, ACMWrapperImpl, tf.filter);
}
static inline ACMWrapperImpl *impl_from_IBaseFilter( IBaseFilter *iface )
{
return CONTAINING_RECORD(iface, ACMWrapperImpl, tf.filter.IBaseFilter_iface);
}
static HRESULT WINAPI ACMWrapper_Receive(TransformFilter *tf, IMediaSample *pSample)
{
ACMWrapperImpl* This = impl_from_TransformFilter(tf);
AM_MEDIA_TYPE amt;
IMediaSample* pOutSample = NULL;
DWORD cbDstStream, cbSrcStream;
@ -65,31 +76,22 @@ static HRESULT ACMWrapper_ProcessSampleData(InputPin *pin, IMediaSample *pSample
MMRESULT res;
HRESULT hr;
LONGLONG tStart = -1, tStop = -1, tMed;
LONGLONG mtStart = -1, mtStop = -1, mtMed;
EnterCriticalSection(&This->tf.csFilter);
if (This->tf.state == State_Stopped)
{
LeaveCriticalSection(&This->tf.csFilter);
return VFW_E_WRONG_STATE;
}
if (pin->end_of_stream || pin->flushing)
{
LeaveCriticalSection(&This->tf.csFilter);
return S_FALSE;
}
EnterCriticalSection(&This->tf.csReceive);
hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
if (FAILED(hr))
{
ERR("Cannot get pointer to sample data (%x)\n", hr);
LeaveCriticalSection(&This->tf.csFilter);
LeaveCriticalSection(&This->tf.csReceive);
return hr;
}
preroll = (IMediaSample_IsPreroll(pSample) == S_OK);
IMediaSample_GetTime(pSample, &tStart, &tStop);
if (IMediaSample_GetMediaTime(pSample, &mtStart, &mtStop) != S_OK)
mtStart = mtStop = -1;
cbSrcStream = IMediaSample_GetActualDataLength(pSample);
/* Prevent discontinuities when codecs 'absorb' data but not give anything back in return */
@ -104,6 +106,7 @@ static HRESULT ACMWrapper_ProcessSampleData(InputPin *pin, IMediaSample *pSample
WARN("Discontinuity\n");
tMed = tStart;
mtMed = mtStart;
TRACE("Sample data ptr = %p, size = %d\n", pbSrcStream, cbSrcStream);
@ -111,7 +114,7 @@ static HRESULT ACMWrapper_ProcessSampleData(InputPin *pin, IMediaSample *pSample
if (FAILED(hr))
{
ERR("Unable to retrieve media type\n");
LeaveCriticalSection(&This->tf.csFilter);
LeaveCriticalSection(&This->tf.csReceive);
return hr;
}
@ -120,11 +123,11 @@ static HRESULT ACMWrapper_ProcessSampleData(InputPin *pin, IMediaSample *pSample
while(hr == S_OK && ash.cbSrcLength)
{
hr = OutputPin_GetDeliveryBuffer((OutputPin*)This->tf.ppPins[1], &pOutSample, NULL, NULL, 0);
hr = BaseOutputPinImpl_GetDeliveryBuffer((BaseOutputPin*)This->tf.ppPins[1], &pOutSample, NULL, NULL, 0);
if (FAILED(hr))
{
ERR("Unable to get delivery buffer (%x)\n", hr);
LeaveCriticalSection(&This->tf.csFilter);
LeaveCriticalSection(&This->tf.csReceive);
return hr;
}
IMediaSample_SetPreroll(pOutSample, preroll);
@ -176,7 +179,7 @@ static HRESULT ACMWrapper_ProcessSampleData(InputPin *pin, IMediaSample *pSample
hr = IMediaSample_SetActualDataLength(pOutSample, ash.cbDstLengthUsed);
assert(hr == S_OK);
/* Bug in acm codecs? It apparantly uses the input, but doesn't necessarily output immediately kl*/
/* Bug in acm codecs? It apparently uses the input, but doesn't necessarily output immediately */
if (!ash.cbSrcLengthUsed)
{
WARN("Sample was skipped? Outputted: %u\n", ash.cbDstLengthUsed);
@ -202,11 +205,26 @@ static HRESULT ACMWrapper_ProcessSampleData(InputPin *pin, IMediaSample *pSample
ERR("No valid timestamp found\n");
IMediaSample_SetTime(pOutSample, NULL, NULL);
}
if (mtStart < 0) {
IMediaSample_SetMediaTime(pOutSample, NULL, NULL);
} else if (ash.cbSrcLengthUsed == cbSrcStream) {
IMediaSample_SetMediaTime(pOutSample, &mtStart, &mtStop);
mtStart = mtMed = mtStop;
} else if (mtStop >= mtStart) {
mtMed = mtStop - mtStart;
mtMed = mtStart + mtMed * ash.cbSrcLengthUsed / cbSrcStream;
IMediaSample_SetMediaTime(pOutSample, &mtStart, &mtMed);
mtStart = mtMed;
} else {
IMediaSample_SetMediaTime(pOutSample, NULL, NULL);
}
TRACE("Sample stop time: %u.%03u\n", (DWORD)(tStart/10000000), (DWORD)((tStart/10000)%1000));
LeaveCriticalSection(&This->tf.csFilter);
hr = OutputPin_SendSample((OutputPin*)This->tf.ppPins[1], pOutSample);
EnterCriticalSection(&This->tf.csFilter);
LeaveCriticalSection(&This->tf.csReceive);
hr = BaseOutputPinImpl_Deliver((BaseOutputPin*)This->tf.ppPins[1], pOutSample);
EnterCriticalSection(&This->tf.csReceive);
if (hr != S_OK && hr != VFW_E_NOT_CONNECTED) {
if (FAILED(hr))
@ -221,8 +239,7 @@ error:
ash.pbSrc += ash.cbSrcLengthUsed;
ash.cbSrcLength -= ash.cbSrcLengthUsed;
if (pOutSample)
IMediaSample_Release(pOutSample);
IMediaSample_Release(pOutSample);
pOutSample = NULL;
}
@ -230,16 +247,19 @@ error:
This->lasttime_real = tStop;
This->lasttime_sent = tMed;
LeaveCriticalSection(&This->tf.csFilter);
LeaveCriticalSection(&This->tf.csReceive);
return hr;
}
static HRESULT ACMWrapper_ConnectInput(InputPin *pin, const AM_MEDIA_TYPE * pmt)
static HRESULT WINAPI ACMWrapper_SetMediaType(TransformFilter *tf, PIN_DIRECTION dir, const AM_MEDIA_TYPE * pmt)
{
ACMWrapperImpl* This = (ACMWrapperImpl *)pin->pin.pinInfo.pFilter;
ACMWrapperImpl* This = impl_from_TransformFilter(tf);
MMRESULT res;
TRACE("(%p)->(%p)\n", This, pmt);
TRACE("(%p)->(%i %p)\n", This, dir, pmt);
if (dir != PINDIR_INPUT)
return S_OK;
/* Check root (GUID w/o FOURCC) */
if ((IsEqualIID(&pmt->majortype, &MEDIATYPE_Audio)) &&
@ -247,7 +267,11 @@ static HRESULT ACMWrapper_ConnectInput(InputPin *pin, const AM_MEDIA_TYPE * pmt)
(IsEqualIID(&pmt->formattype, &FORMAT_WaveFormatEx)))
{
HACMSTREAM drv;
WAVEFORMATEX *wfx = (WAVEFORMATEX*)pmt->pbFormat;
AM_MEDIA_TYPE* outpmt = &This->tf.pmt;
if (!wfx || wfx->wFormatTag == WAVE_FORMAT_PCM || wfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE)
return VFW_E_TYPE_NOT_ACCEPTED;
FreeMediaType(outpmt);
This->pWfIn = (LPWAVEFORMATEX)pmt->pbFormat;
@ -271,8 +295,6 @@ static HRESULT ACMWrapper_ConnectInput(InputPin *pin, const AM_MEDIA_TYPE * pmt)
{
This->has = drv;
/* Update buffer size of media samples in output */
((OutputPin*)This->tf.ppPins[1])->allocProps.cbBuffer = This->pWfOut->nAvgBytesPerSec / 2;
TRACE("Connection accepted\n");
return S_OK;
}
@ -286,28 +308,78 @@ static HRESULT ACMWrapper_ConnectInput(InputPin *pin, const AM_MEDIA_TYPE * pmt)
return VFW_E_TYPE_NOT_ACCEPTED;
}
static HRESULT ACMWrapper_Cleanup(InputPin *pin)
static HRESULT WINAPI ACMWrapper_CompleteConnect(TransformFilter *tf, PIN_DIRECTION dir, IPin *pin)
{
ACMWrapperImpl *This = (ACMWrapperImpl *)pin->pin.pinInfo.pFilter;
ACMWrapperImpl* This = impl_from_TransformFilter(tf);
MMRESULT res;
HACMSTREAM drv;
TRACE("(%p)->()\n", This);
TRACE("(%p)\n", This);
if (This->has)
acmStreamClose(This->has, 0);
if (dir != PINDIR_INPUT)
return S_OK;
This->has = 0;
This->lasttime_real = This->lasttime_sent = -1;
if (!(res = acmStreamOpen(&drv, NULL, This->pWfIn, This->pWfOut, NULL, 0, 0, 0)))
{
This->has = drv;
TRACE("Connection accepted\n");
return S_OK;
}
FIXME("acmStreamOpen returned %d\n", res);
TRACE("Unable to find a suitable ACM decompressor\n");
return VFW_E_TYPE_NOT_ACCEPTED;
}
static HRESULT WINAPI ACMWrapper_BreakConnect(TransformFilter *tf, PIN_DIRECTION dir)
{
ACMWrapperImpl *This = impl_from_TransformFilter(tf);
TRACE("(%p)->(%i)\n", This,dir);
if (dir == PINDIR_INPUT)
{
if (This->has)
acmStreamClose(This->has, 0);
This->has = 0;
This->lasttime_real = This->lasttime_sent = -1;
}
return S_OK;
}
static const TransformFuncsTable ACMWrapper_FuncsTable = {
static HRESULT WINAPI ACMWrapper_DecideBufferSize(TransformFilter *tf, IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest)
{
ACMWrapperImpl *pACM = impl_from_TransformFilter(tf);
ALLOCATOR_PROPERTIES actual;
if (!ppropInputRequest->cbAlign)
ppropInputRequest->cbAlign = 1;
if (ppropInputRequest->cbBuffer < pACM->pWfOut->nAvgBytesPerSec / 2)
ppropInputRequest->cbBuffer = pACM->pWfOut->nAvgBytesPerSec / 2;
if (!ppropInputRequest->cBuffers)
ppropInputRequest->cBuffers = 1;
return IMemAllocator_SetProperties(pAlloc, ppropInputRequest, &actual);
}
static const TransformFilterFuncTable ACMWrapper_FuncsTable = {
ACMWrapper_DecideBufferSize,
NULL,
ACMWrapper_ProcessSampleData,
ACMWrapper_Receive,
NULL,
NULL,
ACMWrapper_ConnectInput,
ACMWrapper_Cleanup
ACMWrapper_SetMediaType,
ACMWrapper_CompleteConnect,
ACMWrapper_BreakConnect,
NULL,
NULL,
NULL,
NULL
};
HRESULT ACMWrapper_create(IUnknown * pUnkOuter, LPVOID * ppv)
@ -322,11 +394,7 @@ HRESULT ACMWrapper_create(IUnknown * pUnkOuter, LPVOID * ppv)
if (pUnkOuter)
return CLASS_E_NOAGGREGATION;
/* Note: This memory is managed by the transform filter once created */
This = CoTaskMemAlloc(sizeof(ACMWrapperImpl));
ZeroMemory(This, sizeof(ACMWrapperImpl));
hr = TransformFilter_Create(&(This->tf), &CLSID_ACMWrapper, &ACMWrapper_FuncsTable, NULL, NULL, NULL);
hr = TransformFilter_Construct(&ACMWrapper_Vtbl, sizeof(ACMWrapperImpl), &CLSID_ACMWrapper, &ACMWrapper_FuncsTable, (IBaseFilter**)&This);
if (FAILED(hr))
return hr;
@ -336,3 +404,22 @@ HRESULT ACMWrapper_create(IUnknown * pUnkOuter, LPVOID * ppv)
return hr;
}
static const IBaseFilterVtbl ACMWrapper_Vtbl =
{
TransformFilterImpl_QueryInterface,
BaseFilterImpl_AddRef,
TransformFilterImpl_Release,
BaseFilterImpl_GetClassID,
TransformFilterImpl_Stop,
TransformFilterImpl_Pause,
TransformFilterImpl_Run,
BaseFilterImpl_GetState,
BaseFilterImpl_SetSyncSource,
BaseFilterImpl_GetSyncSource,
BaseFilterImpl_EnumPins,
TransformFilterImpl_FindPin,
BaseFilterImpl_QueryFilterInfo,
BaseFilterImpl_JoinFilterGraph,
BaseFilterImpl_QueryVendorInfo
};

View file

@ -38,24 +38,37 @@
//#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 )
{
AVIDecImpl* This = (AVIDecImpl*)pTransformFilter;
return CONTAINING_RECORD(iface, AVIDecImpl, tf.filter.IBaseFilter_iface);
}
static inline AVIDecImpl *impl_from_TransformFilter( TransformFilter *iface )
{
return CONTAINING_RECORD(iface, AVIDecImpl, tf.filter);
}
static HRESULT WINAPI AVIDec_StartStreaming(TransformFilter* pTransformFilter)
{
AVIDecImpl* This = impl_from_TransformFilter(pTransformFilter);
DWORD result;
TRACE("(%p)->()\n", This);
This->late = -1;
result = ICDecompressBegin(This->hvid, This->pBihIn, This->pBihOut);
if (result != ICERR_OK)
@ -66,9 +79,39 @@ static HRESULT AVIDec_ProcessBegin(TransformFilterImpl* pTransformFilter)
return S_OK;
}
static HRESULT AVIDec_ProcessSampleData(InputPin *pin, IMediaSample *pSample)
static HRESULT WINAPI AVIDec_EndFlush(TransformFilter *pTransformFilter) {
AVIDecImpl* This = impl_from_TransformFilter(pTransformFilter);
This->late = -1;
return S_OK;
}
static HRESULT WINAPI AVIDec_NotifyDrop(TransformFilter *pTransformFilter, IBaseFilter *sender, Quality qm) {
AVIDecImpl *This = impl_from_TransformFilter(pTransformFilter);
EnterCriticalSection(&This->tf.filter.csFilter);
if (qm.Late > 0)
This->late = qm.Late + qm.TimeStamp;
else
This->late = -1;
LeaveCriticalSection(&This->tf.filter.csFilter);
return S_OK;
}
static int AVIDec_DropSample(AVIDecImpl *This, REFERENCE_TIME tStart) {
if (This->late < 0)
return 0;
if (tStart < This->late) {
TRACE("Dropping sample\n");
return 1;
}
This->late = -1;
return 0;
}
static HRESULT WINAPI AVIDec_Receive(TransformFilter *tf, IMediaSample *pSample)
{
AVIDecImpl* This = (AVIDecImpl *)pin->pin.pinInfo.pFilter;
AVIDecImpl* This = impl_from_TransformFilter(tf);
AM_MEDIA_TYPE amt;
HRESULT hr;
DWORD res;
@ -78,20 +121,9 @@ static HRESULT AVIDec_ProcessSampleData(InputPin *pin, IMediaSample *pSample)
DWORD cbSrcStream;
LPBYTE pbSrcStream;
LONGLONG tStart, tStop;
DWORD flags = 0;
EnterCriticalSection(&This->tf.csFilter);
if (This->tf.state == State_Stopped)
{
LeaveCriticalSection(&This->tf.csFilter);
return VFW_E_WRONG_STATE;
}
if (pin->end_of_stream || pin->flushing)
{
LeaveCriticalSection(&This->tf.csFilter);
return S_FALSE;
}
EnterCriticalSection(&This->tf.csReceive);
hr = IMediaSample_GetPointer(pSample, &pbSrcStream);
if (FAILED(hr))
{
@ -112,7 +144,7 @@ static HRESULT AVIDec_ProcessSampleData(InputPin *pin, IMediaSample *pSample)
/* Update input size to match sample size */
This->pBihIn->biSizeImage = cbSrcStream;
hr = OutputPin_GetDeliveryBuffer((OutputPin*)This->tf.ppPins[1], &pOutSample, NULL, NULL, 0);
hr = BaseOutputPinImpl_GetDeliveryBuffer((BaseOutputPin*)This->tf.ppPins[1], &pOutSample, NULL, NULL, 0);
if (FAILED(hr)) {
ERR("Unable to get delivery buffer (%x)\n", hr);
goto error;
@ -133,39 +165,59 @@ static HRESULT AVIDec_ProcessSampleData(InputPin *pin, IMediaSample *pSample)
goto error;
}
res = ICDecompress(This->hvid, 0, This->pBihIn, pbSrcStream, This->pBihOut, pbDstStream);
if (IMediaSample_IsPreroll(pSample) == S_OK)
flags |= ICDECOMPRESS_PREROLL;
if (IMediaSample_IsSyncPoint(pSample) != S_OK)
flags |= ICDECOMPRESS_NOTKEYFRAME;
hr = IMediaSample_GetTime(pSample, &tStart, &tStop);
if (hr == S_OK && AVIDec_DropSample(This, tStart))
flags |= ICDECOMPRESS_HURRYUP;
res = ICDecompress(This->hvid, flags, This->pBihIn, pbSrcStream, This->pBihOut, pbDstStream);
if (res != ICERR_OK)
ERR("Error occurred during the decompression (%x)\n", res);
/* Drop sample if its intended to be dropped */
if (flags & ICDECOMPRESS_HURRYUP) {
hr = S_OK;
goto error;
}
IMediaSample_SetActualDataLength(pOutSample, This->pBihOut->biSizeImage);
IMediaSample_SetPreroll(pOutSample, (IMediaSample_IsPreroll(pSample) == S_OK));
IMediaSample_SetDiscontinuity(pOutSample, (IMediaSample_IsDiscontinuity(pSample) == S_OK));
IMediaSample_SetSyncPoint(pOutSample, (IMediaSample_IsSyncPoint(pSample) == S_OK));
if (IMediaSample_GetTime(pSample, &tStart, &tStop) == S_OK)
if (hr == S_OK)
IMediaSample_SetTime(pOutSample, &tStart, &tStop);
else if (hr == VFW_S_NO_STOP_TIME)
IMediaSample_SetTime(pOutSample, &tStart, NULL);
else
IMediaSample_SetTime(pOutSample, NULL, NULL);
LeaveCriticalSection(&This->tf.csFilter);
hr = OutputPin_SendSample((OutputPin*)This->tf.ppPins[1], pOutSample);
if (IMediaSample_GetMediaTime(pSample, &tStart, &tStop) == S_OK)
IMediaSample_SetMediaTime(pOutSample, &tStart, &tStop);
else
IMediaSample_SetMediaTime(pOutSample, NULL, NULL);
LeaveCriticalSection(&This->tf.csReceive);
hr = BaseOutputPinImpl_Deliver((BaseOutputPin*)This->tf.ppPins[1], pOutSample);
EnterCriticalSection(&This->tf.csReceive);
if (hr != S_OK && hr != VFW_E_NOT_CONNECTED)
ERR("Error sending sample (%x)\n", hr);
IMediaSample_Release(pOutSample);
return hr;
error:
if (pOutSample)
IMediaSample_Release(pOutSample);
LeaveCriticalSection(&This->tf.csFilter);
LeaveCriticalSection(&This->tf.csReceive);
return hr;
}
static HRESULT AVIDec_ProcessEnd(TransformFilterImpl* pTransformFilter)
static HRESULT WINAPI AVIDec_StopStreaming(TransformFilter* pTransformFilter)
{
AVIDecImpl* This = (AVIDecImpl*)pTransformFilter;
AVIDecImpl* This = impl_from_TransformFilter(pTransformFilter);
DWORD result;
TRACE("(%p)->()\n", This);
@ -182,13 +234,16 @@ static HRESULT AVIDec_ProcessEnd(TransformFilterImpl* pTransformFilter)
return S_OK;
}
static HRESULT AVIDec_ConnectInput(InputPin *pin, const AM_MEDIA_TYPE * pmt)
static HRESULT WINAPI AVIDec_SetMediaType(TransformFilter *tf, PIN_DIRECTION dir, const AM_MEDIA_TYPE * pmt)
{
AVIDecImpl* This = (AVIDecImpl*)pin->pin.pinInfo.pFilter;
AVIDecImpl* This = impl_from_TransformFilter(tf);
HRESULT hr = VFW_E_TYPE_NOT_ACCEPTED;
TRACE("(%p)->(%p)\n", This, pmt);
if (dir != PINDIR_INPUT)
return S_OK;
/* Check root (GUID w/o FOURCC) */
if ((IsEqualIID(&pmt->majortype, &MEDIATYPE_Video)) &&
(!memcmp(((const char *)&pmt->subtype)+4, ((const char *)&MEDIATYPE_Video)+4, sizeof(GUID)-4)))
@ -268,9 +323,6 @@ static HRESULT AVIDec_ConnectInput(InputPin *pin, const AM_MEDIA_TYPE * pmt)
else
assert(0);
/* Update buffer size of media samples in output */
((OutputPin*)This->tf.ppPins[1])->allocProps.cbBuffer = This->pBihOut->biSizeImage;
TRACE("Connection accepted\n");
return S_OK;
}
@ -283,33 +335,69 @@ failed:
return hr;
}
static HRESULT AVIDec_Cleanup(InputPin *pin)
static HRESULT WINAPI AVIDec_CompleteConnect(TransformFilter *tf, PIN_DIRECTION dir, IPin *pin)
{
AVIDecImpl *This = (AVIDecImpl *)pin->pin.pinInfo.pFilter;
AVIDecImpl* This = impl_from_TransformFilter(tf);
TRACE("(%p)->()\n", This);
if (This->hvid)
ICClose(This->hvid);
if (This->pBihIn)
CoTaskMemFree(This->pBihIn);
if (This->pBihOut)
CoTaskMemFree(This->pBihOut);
This->hvid = NULL;
This->pBihIn = NULL;
This->pBihOut = NULL;
TRACE("(%p)\n", This);
return S_OK;
}
static const TransformFuncsTable AVIDec_FuncsTable = {
AVIDec_ProcessBegin,
AVIDec_ProcessSampleData,
AVIDec_ProcessEnd,
static HRESULT WINAPI AVIDec_BreakConnect(TransformFilter *tf, PIN_DIRECTION dir)
{
AVIDecImpl *This = impl_from_TransformFilter(tf);
TRACE("(%p)->()\n", This);
if (dir == PINDIR_INPUT)
{
if (This->hvid)
ICClose(This->hvid);
if (This->pBihIn)
CoTaskMemFree(This->pBihIn);
if (This->pBihOut)
CoTaskMemFree(This->pBihOut);
This->hvid = NULL;
This->pBihIn = NULL;
This->pBihOut = NULL;
}
return S_OK;
}
static HRESULT WINAPI AVIDec_DecideBufferSize(TransformFilter *tf, IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest)
{
AVIDecImpl *pAVI = impl_from_TransformFilter(tf);
ALLOCATOR_PROPERTIES actual;
if (!ppropInputRequest->cbAlign)
ppropInputRequest->cbAlign = 1;
if (ppropInputRequest->cbBuffer < pAVI->pBihOut->biSizeImage)
ppropInputRequest->cbBuffer = pAVI->pBihOut->biSizeImage;
if (!ppropInputRequest->cBuffers)
ppropInputRequest->cBuffers = 1;
return IMemAllocator_SetProperties(pAlloc, ppropInputRequest, &actual);
}
static const TransformFilterFuncTable AVIDec_FuncsTable = {
AVIDec_DecideBufferSize,
AVIDec_StartStreaming,
AVIDec_Receive,
AVIDec_StopStreaming,
NULL,
AVIDec_ConnectInput,
AVIDec_Cleanup
AVIDec_SetMediaType,
AVIDec_CompleteConnect,
AVIDec_BreakConnect,
NULL,
NULL,
AVIDec_EndFlush,
NULL,
AVIDec_NotifyDrop
};
HRESULT AVIDec_create(IUnknown * pUnkOuter, LPVOID * ppv)
@ -324,19 +412,35 @@ HRESULT AVIDec_create(IUnknown * pUnkOuter, LPVOID * ppv)
if (pUnkOuter)
return CLASS_E_NOAGGREGATION;
/* Note: This memory is managed by the transform filter once created */
This = CoTaskMemAlloc(sizeof(AVIDecImpl));
hr = TransformFilter_Construct(&AVIDec_Vtbl, sizeof(AVIDecImpl), &CLSID_AVIDec, &AVIDec_FuncsTable, (IBaseFilter**)&This);
if (FAILED(hr))
return hr;
This->hvid = NULL;
This->pBihIn = NULL;
This->pBihOut = NULL;
hr = TransformFilter_Create(&(This->tf), &CLSID_AVIDec, &AVIDec_FuncsTable, NULL, NULL, NULL);
if (FAILED(hr))
return hr;
*ppv = This;
return hr;
}
static const IBaseFilterVtbl AVIDec_Vtbl =
{
TransformFilterImpl_QueryInterface,
BaseFilterImpl_AddRef,
TransformFilterImpl_Release,
BaseFilterImpl_GetClassID,
TransformFilterImpl_Stop,
TransformFilterImpl_Pause,
TransformFilterImpl_Run,
BaseFilterImpl_GetState,
BaseFilterImpl_SetSyncSource,
BaseFilterImpl_GetSyncSource,
BaseFilterImpl_EnumPins,
TransformFilterImpl_FindPin,
BaseFilterImpl_QueryFilterInfo,
BaseFilterImpl_JoinFilterGraph,
BaseFilterImpl_QueryVendorInfo
};

View file

@ -30,7 +30,6 @@
*/
#include "quartz_private.h"
#include "control_private.h"
#include "pin.h"
//#include "uuids.h"
@ -101,6 +100,11 @@ struct thread_args {
DWORD stream;
};
static inline AVISplitterImpl *impl_from_IMediaSeeking( IMediaSeeking *iface )
{
return CONTAINING_RECORD(iface, AVISplitterImpl, Parser.sourceSeeking.IMediaSeeking_iface);
}
/* The threading stuff cries for an explanation
*
* PullPin starts processing and calls AVISplitter_first_request
@ -284,9 +288,9 @@ static HRESULT AVISplitter_next_request(AVISplitterImpl *This, DWORD streamnumbe
static HRESULT AVISplitter_Receive(AVISplitterImpl *This, IMediaSample *sample, DWORD streamnumber)
{
Parser_OutputPin *pin = (Parser_OutputPin *)This->Parser.ppPins[1+streamnumber];
Parser_OutputPin *pin = unsafe_impl_Parser_OutputPin_from_IPin(This->Parser.ppPins[1+streamnumber]);
HRESULT hr;
LONGLONG start, stop;
LONGLONG start, stop, rtstart, rtstop;
StreamData *stream = &This->streams[streamnumber];
start = pin->dwSamplesProcessed;
@ -309,9 +313,31 @@ static HRESULT AVISplitter_Receive(AVISplitterImpl *This, IMediaSample *sample,
stop *= 10000000;
stop /= stream->streamheader.dwRate;
IMediaSample_SetTime(sample, &start, &stop);
if (IMediaSample_IsDiscontinuity(sample) == S_OK) {
IPin *victim;
EnterCriticalSection(&This->Parser.filter.csFilter);
pin->pin.pin.tStart = start;
pin->pin.pin.dRate = This->Parser.sourceSeeking.dRate;
hr = IPin_ConnectedTo(&pin->pin.pin.IPin_iface, &victim);
if (hr == S_OK)
{
hr = IPin_NewSegment(victim, start, This->Parser.sourceSeeking.llStop,
This->Parser.sourceSeeking.dRate);
if (hr != S_OK)
FIXME("NewSegment returns %08x\n", hr);
IPin_Release(victim);
}
LeaveCriticalSection(&This->Parser.filter.csFilter);
if (hr != S_OK)
return hr;
}
rtstart = (double)(start - pin->pin.pin.tStart) / pin->pin.pin.dRate;
rtstop = (double)(stop - pin->pin.pin.tStart) / pin->pin.pin.dRate;
hr = IMediaSample_SetMediaTime(sample, &start, &stop);
IMediaSample_SetTime(sample, &rtstart, &rtstop);
IMediaSample_SetMediaTime(sample, &start, &stop);
hr = OutputPin_SendSample(&pin->pin, sample);
hr = BaseOutputPinImpl_Deliver(&pin->pin, sample);
/* Uncomment this if you want to debug the time differences between the
* different streams, it is useful for that
@ -373,7 +399,7 @@ static HRESULT AVISplitter_Sample(LPVOID iface, IMediaSample * pSample, DWORD_PT
return S_OK;
}
/* Send the sample to whatever thread is appropiate
/* Send the sample to whatever thread is appropriate
* That thread should also not have a sample queued at the moment
*/
/* Debugging */
@ -421,6 +447,9 @@ static HRESULT AVISplitter_first_request(LPVOID iface)
stream->pos_next = stream->pos;
stream->index_next = stream->index;
/* This was sent after stopped->paused or stopped->playing, so set seek */
stream->seek = 1;
/* There should be a packet queued from AVISplitter_next_request last time
* It needs to be done now because this is the only way to ensure that every
* stream will have at least 1 packet processed
@ -530,13 +559,13 @@ static HRESULT AVISplitter_ProcessIndex(AVISplitterImpl *This, AVISTDINDEX **ind
if (!pIndex)
return E_OUTOFMEMORY;
IAsyncReader_SyncRead(((PullPin *)This->Parser.ppPins[0])->pReader, qwOffset, cb, (BYTE *)pIndex);
IAsyncReader_SyncRead((impl_PullPin_from_IPin(This->Parser.ppPins[0]))->pReader, qwOffset, cb, (BYTE *)pIndex);
rest = cb - sizeof(AVISUPERINDEX) + sizeof(RIFFCHUNK) + sizeof(pIndex->aIndex);
TRACE("FOURCC: %s\n", debugstr_an((char *)&pIndex->fcc, 4));
TRACE("wLongsPerEntry: %hd\n", pIndex->wLongsPerEntry);
TRACE("bIndexSubType: %hd\n", pIndex->bIndexSubType);
TRACE("bIndexType: %hd\n", pIndex->bIndexType);
TRACE("bIndexSubType: %u\n", pIndex->bIndexSubType);
TRACE("bIndexType: %u\n", pIndex->bIndexType);
TRACE("nEntriesInUse: %u\n", pIndex->nEntriesInUse);
TRACE("dwChunkId: %.4s\n", (char *)&pIndex->dwChunkId);
TRACE("qwBaseOffset: %x%08x\n", (DWORD)(pIndex->qwBaseOffset >> 32), (DWORD)pIndex->qwBaseOffset);
@ -785,8 +814,8 @@ static HRESULT AVISplitter_ProcessStreamList(AVISplitterImpl * This, const BYTE
}
TRACE("wLongsPerEntry: %hd\n", pIndex->wLongsPerEntry);
TRACE("bIndexSubType: %hd\n", pIndex->bIndexSubType);
TRACE("bIndexType: %hd\n", pIndex->bIndexType);
TRACE("bIndexSubType: %u\n", pIndex->bIndexSubType);
TRACE("bIndexType: %u\n", pIndex->bIndexType);
TRACE("nEntriesInUse: %u\n", pIndex->nEntriesInUse);
TRACE("dwChunkId: %.4s\n", (const char *)&pIndex->dwChunkId);
if (pIndex->dwReserved[0])
@ -899,7 +928,7 @@ static HRESULT AVISplitter_InitializeStreams(AVISplitterImpl *This)
nMax = This->oldindex->cb / sizeof(This->oldindex->aIndex[0]);
/* Ok, maybe this is more of an excercise to see if I interpret everything correctly or not, but that is useful for now. */
/* Ok, maybe this is more of an exercise to see if I interpret everything correctly or not, but that is useful for now. */
for (n = 0; n < nMax; ++n)
{
DWORD streamId = StreamFromFOURCC(This->oldindex->aIndex[n].dwChunkId);
@ -970,16 +999,16 @@ static HRESULT AVISplitter_InitializeStreams(AVISplitterImpl *This)
frames *= stream->streamheader.dwScale;
/* Keep accuracy as high as possible for duration */
This->Parser.mediaSeeking.llDuration = frames * 10000000;
This->Parser.mediaSeeking.llDuration /= stream->streamheader.dwRate;
This->Parser.mediaSeeking.llStop = This->Parser.mediaSeeking.llDuration;
This->Parser.mediaSeeking.llCurrent = 0;
This->Parser.sourceSeeking.llDuration = frames * 10000000;
This->Parser.sourceSeeking.llDuration /= stream->streamheader.dwRate;
This->Parser.sourceSeeking.llStop = This->Parser.sourceSeeking.llDuration;
This->Parser.sourceSeeking.llCurrent = 0;
frames /= stream->streamheader.dwRate;
TRACE("Duration: %d days, %d hours, %d minutes and %d.%03u seconds\n", (DWORD)(frames / 86400),
(DWORD)((frames % 86400) / 3600), (DWORD)((frames % 3600) / 60), (DWORD)(frames % 60),
(DWORD)(This->Parser.mediaSeeking.llDuration/10000) % 1000);
(DWORD)(This->Parser.sourceSeeking.llDuration/10000) % 1000);
}
return S_OK;
@ -990,7 +1019,7 @@ static HRESULT AVISplitter_Disconnect(LPVOID iface);
/* FIXME: fix leaks on failure here */
static HRESULT AVISplitter_InputPin_PreConnect(IPin * iface, IPin * pConnectPin, ALLOCATOR_PROPERTIES *props)
{
PullPin *This = (PullPin *)iface;
PullPin *This = impl_PullPin_from_IPin(iface);
HRESULT hr;
RIFFLIST list;
LONGLONG pos = 0; /* in bytes */
@ -1239,7 +1268,7 @@ static ULONG WINAPI AVISplitter_Release(IBaseFilter *iface)
AVISplitterImpl *This = (AVISplitterImpl *)iface;
ULONG ref;
ref = InterlockedDecrement(&This->Parser.refCount);
ref = InterlockedDecrement(&This->Parser.filter.refCount);
TRACE("(%p)->() Release from %d\n", This, ref + 1);
@ -1252,15 +1281,15 @@ static ULONG WINAPI AVISplitter_Release(IBaseFilter *iface)
return ref;
}
static HRESULT AVISplitter_seek(IBaseFilter *iface)
static HRESULT WINAPI AVISplitter_seek(IMediaSeeking *iface)
{
AVISplitterImpl *This = (AVISplitterImpl *)iface;
AVISplitterImpl *This = impl_from_IMediaSeeking(iface);
PullPin *pPin = This->Parser.pInputPin;
LONGLONG newpos, endpos;
DWORD x;
newpos = This->Parser.mediaSeeking.llCurrent;
endpos = This->Parser.mediaSeeking.llDuration;
newpos = This->Parser.sourceSeeking.llCurrent;
endpos = This->Parser.sourceSeeking.llDuration;
if (newpos > endpos)
{
@ -1272,15 +1301,14 @@ static HRESULT AVISplitter_seek(IBaseFilter *iface)
EnterCriticalSection(&pPin->thread_lock);
/* Send a flush to all output pins */
IPin_BeginFlush((IPin *)pPin);
IPin_BeginFlush(&pPin->pin.IPin_iface);
/* Make sure this is done while stopped, BeginFlush takes care of this */
EnterCriticalSection(&This->Parser.csFilter);
EnterCriticalSection(&This->Parser.filter.csFilter);
for (x = 0; x < This->Parser.cStreams; ++x)
{
Parser_OutputPin *pin = (Parser_OutputPin *)This->Parser.ppPins[1+x];
Parser_OutputPin *pin = unsafe_impl_Parser_OutputPin_from_IPin(This->Parser.ppPins[1+x]);
StreamData *stream = This->streams + x;
IPin *victim = NULL;
LONGLONG wanted_frames;
DWORD last_keyframe = 0, last_keyframeidx = 0, preroll = 0;
@ -1289,13 +1317,6 @@ static HRESULT AVISplitter_seek(IBaseFilter *iface)
wanted_frames /= 10000000;
wanted_frames /= stream->streamheader.dwScale;
IPin_ConnectedTo((IPin *)pin, &victim);
if (victim)
{
IPin_NewSegment(victim, newpos, endpos, pPin->dRate);
IPin_Release(victim);
}
pin->dwSamplesProcessed = 0;
stream->index = 0;
stream->pos = 0;
@ -1377,10 +1398,10 @@ static HRESULT AVISplitter_seek(IBaseFilter *iface)
stream->preroll = preroll;
stream->seek = 1;
}
LeaveCriticalSection(&This->Parser.csFilter);
LeaveCriticalSection(&This->Parser.filter.csFilter);
TRACE("Done flushing\n");
IPin_EndFlush((IPin *)pPin);
IPin_EndFlush(&pPin->pin.IPin_iface);
LeaveCriticalSection(&pPin->thread_lock);
return S_OK;

View file

@ -1,921 +0,0 @@
/*
* Filter Seeking and Control Interfaces
*
* Copyright 2003 Robert Shearman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
/* FIXME: critical sections */
#include "quartz_private.h"
#include "control_private.h"
//#include "uuids.h"
#include <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
};

View file

@ -1,62 +0,0 @@
/*
* Filter Seeking and Control Interfaces
*
* Copyright 2003 Robert Shearman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef QUARTZ_CONTROL_H
#define QUARTZ_CONTROL_H
typedef HRESULT (* CHANGEPROC)(IBaseFilter *pUserData);
typedef struct MediaSeekingImpl
{
const IMediaSeekingVtbl * lpVtbl;
ULONG refCount;
IBaseFilter *pUserData;
CHANGEPROC fnChangeStop;
CHANGEPROC fnChangeCurrent;
CHANGEPROC fnChangeRate;
DWORD dwCapabilities;
double dRate;
LONGLONG llCurrent, llStop, llDuration;
GUID timeformat;
PCRITICAL_SECTION crst;
} MediaSeekingImpl;
HRESULT MediaSeekingImpl_Init(IBaseFilter *pUserData, CHANGEPROC fnChangeStop, CHANGEPROC fnChangeCurrent, CHANGEPROC fnChangeRate, MediaSeekingImpl * pSeeking, PCRITICAL_SECTION crit_sect);
HRESULT WINAPI MediaSeekingImpl_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities);
HRESULT WINAPI MediaSeekingImpl_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities);
HRESULT WINAPI MediaSeekingImpl_IsFormatSupported(IMediaSeeking * iface, const GUID * pFormat);
HRESULT WINAPI MediaSeekingImpl_QueryPreferredFormat(IMediaSeeking * iface, GUID * pFormat);
HRESULT WINAPI MediaSeekingImpl_GetTimeFormat(IMediaSeeking * iface, GUID * pFormat);
HRESULT WINAPI MediaSeekingImpl_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat);
HRESULT WINAPI MediaSeekingImpl_SetTimeFormat(IMediaSeeking * iface, const GUID * pFormat);
HRESULT WINAPI MediaSeekingImpl_GetDuration(IMediaSeeking * iface, LONGLONG * pDuration);
HRESULT WINAPI MediaSeekingImpl_GetStopPosition(IMediaSeeking * iface, LONGLONG * pStop);
HRESULT WINAPI MediaSeekingImpl_GetCurrentPosition(IMediaSeeking * iface, LONGLONG * pCurrent);
HRESULT WINAPI MediaSeekingImpl_ConvertTimeFormat(IMediaSeeking * iface, LONGLONG * pTarget, const GUID * pTargetFormat, LONGLONG Source, const GUID * pSourceFormat);
HRESULT WINAPI MediaSeekingImpl_SetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, DWORD dwCurrentFlags, LONGLONG * pStop, DWORD dwStopFlags);
HRESULT WINAPI MediaSeekingImpl_GetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, LONGLONG * pStop);
HRESULT WINAPI MediaSeekingImpl_GetAvailable(IMediaSeeking * iface, LONGLONG * pEarliest, LONGLONG * pLatest);
HRESULT WINAPI MediaSeekingImpl_SetRate(IMediaSeeking * iface, double dRate);
HRESULT WINAPI MediaSeekingImpl_GetRate(IMediaSeeking * iface, double * dRate);
HRESULT WINAPI MediaSeekingImpl_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll);
#endif /*QUARTZ_CONTROL_H*/

View file

@ -1,6 +1,4 @@
/*
* Copyright (C) 2002 Robert Shearman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@ -16,15 +14,4 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
import "objidl.idl";
#include <devenum.idl>
#include <axcore.idl>
#include <axextend.idl>
#include <dyngraph.idl>
/* TODO: #include <dvdif.h> */
#include <vmrender.idl>
#include "control.idl"

View file

@ -0,0 +1,20 @@
HKCR
{
NoRemove Typelib
{
NoRemove '{56A868B0-0AD4-11CE-B03A-0020AF0BA770}'
{
'1.0' = s 'QuartzTypeLib'
{
'0' { win32 = s '%MODULE%' }
FLAGS = s '0'
}
}
}
NoRemove Interface
{
}
NoRemove CLSID
{
}
}

File diff suppressed because it is too large Load diff

View file

@ -26,22 +26,31 @@ WINE_DEFAULT_DEBUG_CHANNEL(quartz);
typedef struct IEnumFiltersImpl
{
const IEnumFiltersVtbl * lpVtbl;
IEnumFilters IEnumFilters_iface;
LONG refCount;
IBaseFilter ** ppFilters;
int nFilters;
IGraphVersion * pVersionSource;
LONG Version;
IBaseFilter *** pppFilters;
ULONG * pNumFilters;
ULONG uIndex;
} IEnumFiltersImpl;
static const struct IEnumFiltersVtbl IEnumFiltersImpl_Vtbl;
HRESULT IEnumFiltersImpl_Construct(IBaseFilter ** ppFilters, ULONG nFilters, IEnumFilters ** ppEnum)
static inline IEnumFiltersImpl *impl_from_IEnumFilters(IEnumFilters *iface)
{
return CONTAINING_RECORD(iface, IEnumFiltersImpl, IEnumFilters_iface);
}
HRESULT IEnumFiltersImpl_Construct(IGraphVersion * pVersionSource, IBaseFilter *** pppFilters, ULONG * pNumFilters, IEnumFilters ** ppEnum)
{
/* Note: The incoming IBaseFilter interfaces are not AddRef'd here as in Windows,
* they should have been previously AddRef'd. */
IEnumFiltersImpl * pEnumFilters = CoTaskMemAlloc(sizeof(IEnumFiltersImpl));
HRESULT hr;
LONG currentVersion;
TRACE("(%p, %d, %p)\n", ppFilters, nFilters, ppEnum);
TRACE("(%p, %p, %p)\n", pppFilters, pNumFilters, ppEnum);
*ppEnum = NULL;
@ -50,20 +59,19 @@ HRESULT IEnumFiltersImpl_Construct(IBaseFilter ** ppFilters, ULONG nFilters, IEn
return E_OUTOFMEMORY;
}
pEnumFilters->lpVtbl = &IEnumFiltersImpl_Vtbl;
pEnumFilters->IEnumFilters_iface.lpVtbl = &IEnumFiltersImpl_Vtbl;
pEnumFilters->refCount = 1;
pEnumFilters->uIndex = 0;
pEnumFilters->nFilters = nFilters;
pEnumFilters->ppFilters = CoTaskMemAlloc(sizeof(IBaseFilter*) * nFilters);
if (!pEnumFilters->ppFilters)
{
CoTaskMemFree(pEnumFilters);
return E_OUTOFMEMORY;
}
pEnumFilters->pNumFilters = pNumFilters;
pEnumFilters->pppFilters = pppFilters;
IGraphVersion_AddRef(pVersionSource);
pEnumFilters->pVersionSource = pVersionSource;
memcpy(pEnumFilters->ppFilters, ppFilters, nFilters * sizeof(IBaseFilter*));
/* Store the current version of the graph */
hr = IGraphVersion_QueryVersion(pVersionSource, &currentVersion);
pEnumFilters->Version = (hr==S_OK) ? currentVersion : 0;
*ppEnum = (IEnumFilters *)(&pEnumFilters->lpVtbl);
*ppEnum = &pEnumFilters->IEnumFilters_iface;
return S_OK;
}
@ -91,7 +99,7 @@ static HRESULT WINAPI IEnumFiltersImpl_QueryInterface(IEnumFilters * iface, REFI
static ULONG WINAPI IEnumFiltersImpl_AddRef(IEnumFilters * iface)
{
IEnumFiltersImpl *This = (IEnumFiltersImpl *)iface;
IEnumFiltersImpl *This = impl_from_IEnumFilters(iface);
ULONG refCount = InterlockedIncrement(&This->refCount);
TRACE("(%p)->()\n", iface);
@ -101,15 +109,14 @@ static ULONG WINAPI IEnumFiltersImpl_AddRef(IEnumFilters * iface)
static ULONG WINAPI IEnumFiltersImpl_Release(IEnumFilters * iface)
{
IEnumFiltersImpl *This = (IEnumFiltersImpl *)iface;
IEnumFiltersImpl *This = impl_from_IEnumFilters(iface);
ULONG refCount = InterlockedDecrement(&This->refCount);
TRACE("(%p)->()\n", iface);
if (!refCount)
{
CoTaskMemFree(This->ppFilters);
CoTaskMemFree(This);
IGraphVersion_Release(This->pVersionSource);
return 0;
}
else
@ -120,18 +127,26 @@ static HRESULT WINAPI IEnumFiltersImpl_Next(IEnumFilters * iface, ULONG cFilters
{
ULONG cFetched;
ULONG i;
IEnumFiltersImpl *This = (IEnumFiltersImpl *)iface;
LONG currentVersion;
IEnumFiltersImpl *This = impl_from_IEnumFilters(iface);
HRESULT hr;
cFetched = min(This->nFilters, This->uIndex + cFilters) - This->uIndex;
cFetched = min(*This->pNumFilters, This->uIndex + cFilters) - This->uIndex;
TRACE("(%p)->(%u, %p, %p)\n", iface, cFilters, ppFilters, pcFetched);
/* First of all check if the graph has changed */
hr = IGraphVersion_QueryVersion(This->pVersionSource, &currentVersion);
if (hr==S_OK && This->Version != currentVersion)
return VFW_E_ENUM_OUT_OF_SYNC;
if (!ppFilters)
return E_POINTER;
for (i = 0; i < cFetched; i++)
{
ppFilters[i] = This->ppFilters[This->uIndex + i];
ppFilters[i] = (*This->pppFilters)[This->uIndex + i];
IBaseFilter_AddRef(ppFilters[i]);
}
@ -147,11 +162,11 @@ static HRESULT WINAPI IEnumFiltersImpl_Next(IEnumFilters * iface, ULONG cFilters
static HRESULT WINAPI IEnumFiltersImpl_Skip(IEnumFilters * iface, ULONG cFilters)
{
IEnumFiltersImpl *This = (IEnumFiltersImpl *)iface;
IEnumFiltersImpl *This = impl_from_IEnumFilters(iface);
TRACE("(%p)->(%u)\n", iface, cFilters);
if (This->uIndex + cFilters < This->nFilters)
if (This->uIndex + cFilters < *This->pNumFilters)
{
This->uIndex += cFilters;
return S_OK;
@ -161,22 +176,27 @@ static HRESULT WINAPI IEnumFiltersImpl_Skip(IEnumFilters * iface, ULONG cFilters
static HRESULT WINAPI IEnumFiltersImpl_Reset(IEnumFilters * iface)
{
IEnumFiltersImpl *This = (IEnumFiltersImpl *)iface;
IEnumFiltersImpl *This = impl_from_IEnumFilters(iface);
HRESULT hr;
LONG currentVersion;
TRACE("(%p)->()\n", iface);
This->uIndex = 0;
hr = IGraphVersion_QueryVersion(This->pVersionSource, &currentVersion);
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);

View file

@ -24,237 +24,9 @@
WINE_DEFAULT_DEBUG_CHANNEL(quartz);
HRESULT CopyMediaType(AM_MEDIA_TYPE * pDest, const AM_MEDIA_TYPE *pSrc)
{
*pDest = *pSrc;
if (!pSrc->pbFormat) return S_OK;
if (!(pDest->pbFormat = CoTaskMemAlloc(pSrc->cbFormat)))
return E_OUTOFMEMORY;
memcpy(pDest->pbFormat, pSrc->pbFormat, pSrc->cbFormat);
if (pDest->pUnk)
IUnknown_AddRef(pDest->pUnk);
return S_OK;
}
void FreeMediaType(AM_MEDIA_TYPE * pMediaType)
{
if (pMediaType->pbFormat)
{
CoTaskMemFree(pMediaType->pbFormat);
pMediaType->pbFormat = NULL;
}
if (pMediaType->pUnk)
{
IUnknown_Release(pMediaType->pUnk);
pMediaType->pUnk = NULL;
}
}
static AM_MEDIA_TYPE * CreateMediaType(AM_MEDIA_TYPE const * pSrc)
{
AM_MEDIA_TYPE * pDest;
pDest = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
if (!pDest)
return NULL;
if (FAILED(CopyMediaType(pDest, pSrc)))
{
CoTaskMemFree(pDest);
return NULL;
}
return pDest;
}
void DeleteMediaType(AM_MEDIA_TYPE * pMediaType)
{
FreeMediaType(pMediaType);
CoTaskMemFree(pMediaType);
}
BOOL CompareMediaTypes(const AM_MEDIA_TYPE * pmt1, const AM_MEDIA_TYPE * pmt2, BOOL bWildcards)
{
TRACE("pmt1: ");
dump_AM_MEDIA_TYPE(pmt1);
TRACE("pmt2: ");
dump_AM_MEDIA_TYPE(pmt2);
return (((bWildcards && (IsEqualGUID(&pmt1->majortype, &GUID_NULL) || IsEqualGUID(&pmt2->majortype, &GUID_NULL))) || IsEqualGUID(&pmt1->majortype, &pmt2->majortype)) &&
((bWildcards && (IsEqualGUID(&pmt1->subtype, &GUID_NULL) || IsEqualGUID(&pmt2->subtype, &GUID_NULL))) || IsEqualGUID(&pmt1->subtype, &pmt2->subtype)));
}
void dump_AM_MEDIA_TYPE(const AM_MEDIA_TYPE * pmt)
{
if (!pmt)
return;
TRACE("\t%s\n\t%s\n\t...\n\t%s\n", qzdebugstr_guid(&pmt->majortype), qzdebugstr_guid(&pmt->subtype), qzdebugstr_guid(&pmt->formattype));
}
typedef struct IEnumMediaTypesImpl
{
const IEnumMediaTypesVtbl * lpVtbl;
LONG refCount;
ENUMMEDIADETAILS enumMediaDetails;
ULONG uIndex;
} IEnumMediaTypesImpl;
static const struct IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl;
HRESULT IEnumMediaTypesImpl_Construct(const ENUMMEDIADETAILS * pDetails, IEnumMediaTypes ** ppEnum)
{
ULONG i;
IEnumMediaTypesImpl * pEnumMediaTypes = CoTaskMemAlloc(sizeof(IEnumMediaTypesImpl));
if (!pEnumMediaTypes)
{
*ppEnum = NULL;
return E_OUTOFMEMORY;
}
pEnumMediaTypes->lpVtbl = &IEnumMediaTypesImpl_Vtbl;
pEnumMediaTypes->refCount = 1;
pEnumMediaTypes->uIndex = 0;
pEnumMediaTypes->enumMediaDetails.cMediaTypes = pDetails->cMediaTypes;
pEnumMediaTypes->enumMediaDetails.pMediaTypes = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE) * pDetails->cMediaTypes);
for (i = 0; i < pDetails->cMediaTypes; i++)
if (FAILED(CopyMediaType(&pEnumMediaTypes->enumMediaDetails.pMediaTypes[i], &pDetails->pMediaTypes[i])))
{
while (i--)
CoTaskMemFree(pEnumMediaTypes->enumMediaDetails.pMediaTypes[i].pbFormat);
CoTaskMemFree(pEnumMediaTypes->enumMediaDetails.pMediaTypes);
return E_OUTOFMEMORY;
}
*ppEnum = (IEnumMediaTypes *)(&pEnumMediaTypes->lpVtbl);
return S_OK;
}
static HRESULT WINAPI IEnumMediaTypesImpl_QueryInterface(IEnumMediaTypes * iface, REFIID riid, LPVOID * ppv)
{
TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv);
*ppv = NULL;
if (IsEqualIID(riid, &IID_IUnknown))
*ppv = iface;
else if (IsEqualIID(riid, &IID_IEnumMediaTypes))
*ppv = iface;
if (*ppv)
{
IUnknown_AddRef((IUnknown *)(*ppv));
return S_OK;
}
FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
return E_NOINTERFACE;
}
static ULONG WINAPI IEnumMediaTypesImpl_AddRef(IEnumMediaTypes * iface)
{
IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
ULONG refCount = InterlockedIncrement(&This->refCount);
TRACE("(%p)->() AddRef from %d\n", iface, refCount - 1);
return refCount;
}
static ULONG WINAPI IEnumMediaTypesImpl_Release(IEnumMediaTypes * iface)
{
IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
ULONG refCount = InterlockedDecrement(&This->refCount);
TRACE("(%p)->() Release from %d\n", iface, refCount + 1);
if (!refCount)
{
ULONG i;
for (i = 0; i < This->enumMediaDetails.cMediaTypes; i++)
if (This->enumMediaDetails.pMediaTypes[i].pbFormat)
CoTaskMemFree(This->enumMediaDetails.pMediaTypes[i].pbFormat);
CoTaskMemFree(This->enumMediaDetails.pMediaTypes);
CoTaskMemFree(This);
}
return refCount;
}
static HRESULT WINAPI IEnumMediaTypesImpl_Next(IEnumMediaTypes * iface, ULONG cMediaTypes, AM_MEDIA_TYPE ** ppMediaTypes, ULONG * pcFetched)
{
ULONG cFetched;
IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
cFetched = min(This->enumMediaDetails.cMediaTypes, This->uIndex + cMediaTypes) - This->uIndex;
TRACE("(%u, %p, %p)\n", cMediaTypes, ppMediaTypes, pcFetched);
TRACE("Next uIndex: %u, cFetched: %u\n", This->uIndex, cFetched);
if (cFetched > 0)
{
ULONG i;
for (i = 0; i < cFetched; i++)
if (!(ppMediaTypes[i] = CreateMediaType(&This->enumMediaDetails.pMediaTypes[This->uIndex + i])))
{
while (i--)
DeleteMediaType(ppMediaTypes[i]);
*pcFetched = 0;
return E_OUTOFMEMORY;
}
}
if ((cMediaTypes != 1) || pcFetched)
*pcFetched = cFetched;
This->uIndex += cFetched;
if (cFetched != cMediaTypes)
return S_FALSE;
return S_OK;
}
static HRESULT WINAPI IEnumMediaTypesImpl_Skip(IEnumMediaTypes * iface, ULONG cMediaTypes)
{
IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
TRACE("(%u)\n", cMediaTypes);
if (This->uIndex + cMediaTypes < This->enumMediaDetails.cMediaTypes)
{
This->uIndex += cMediaTypes;
return S_OK;
}
return S_FALSE;
}
static HRESULT WINAPI IEnumMediaTypesImpl_Reset(IEnumMediaTypes * iface)
{
IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
TRACE("()\n");
This->uIndex = 0;
return S_OK;
}
static HRESULT WINAPI IEnumMediaTypesImpl_Clone(IEnumMediaTypes * iface, IEnumMediaTypes ** ppEnum)
{
HRESULT hr;
IEnumMediaTypesImpl *This = (IEnumMediaTypesImpl *)iface;
TRACE("(%p)\n", ppEnum);
hr = IEnumMediaTypesImpl_Construct(&This->enumMediaDetails, ppEnum);
if (FAILED(hr))
return hr;
return IEnumMediaTypes_Skip(*ppEnum, This->uIndex);
}
static const IEnumMediaTypesVtbl IEnumMediaTypesImpl_Vtbl =
{
IEnumMediaTypesImpl_QueryInterface,
IEnumMediaTypesImpl_AddRef,
IEnumMediaTypesImpl_Release,
IEnumMediaTypesImpl_Next,
IEnumMediaTypesImpl_Skip,
IEnumMediaTypesImpl_Reset,
IEnumMediaTypesImpl_Clone
};

View file

@ -3,9 +3,6 @@
*
* Copyright 2003 Robert Shearman
*
* This file contains the (internal) driver registration functions,
* driver enumeration APIs and DirectDraw creation functions.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@ -31,7 +28,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(quartz);
typedef struct EnumMonikerImpl
{
const IEnumMonikerVtbl *lpVtbl;
IEnumMoniker IEnumMoniker_iface;
LONG ref;
IMoniker ** ppMoniker;
ULONG nMonikerCount;
@ -40,6 +37,11 @@ typedef struct EnumMonikerImpl
static const IEnumMonikerVtbl EnumMonikerImpl_Vtbl;
static inline EnumMonikerImpl *impl_from_IEnumMoniker(IEnumMoniker *iface)
{
return CONTAINING_RECORD(iface, EnumMonikerImpl, IEnumMoniker_iface);
}
static ULONG WINAPI EnumMonikerImpl_AddRef(LPENUMMONIKER iface);
HRESULT EnumMonikerImpl_Create(IMoniker ** ppMoniker, ULONG nMonikerCount, IEnumMoniker ** ppEnum)
@ -56,14 +58,14 @@ HRESULT EnumMonikerImpl_Create(IMoniker ** ppMoniker, ULONG nMonikerCount, IEnum
if (!pemi)
return E_OUTOFMEMORY;
pemi->lpVtbl = &EnumMonikerImpl_Vtbl;
pemi->IEnumMoniker_iface.lpVtbl = &EnumMonikerImpl_Vtbl;
pemi->ref = 1;
pemi->ppMoniker = CoTaskMemAlloc(nMonikerCount * sizeof(IMoniker*));
memcpy(pemi->ppMoniker, ppMoniker, nMonikerCount*sizeof(IMoniker*));
pemi->nMonikerCount = nMonikerCount;
pemi->index = 0;
*ppEnum = (IEnumMoniker *)pemi;
*ppEnum = &pemi->IEnumMoniker_iface;
return S_OK;
}
@ -76,7 +78,7 @@ static HRESULT WINAPI EnumMonikerImpl_QueryInterface(
REFIID riid,
LPVOID *ppvObj)
{
EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
if (This == NULL || ppvObj == NULL) return E_POINTER;
@ -99,7 +101,7 @@ static HRESULT WINAPI EnumMonikerImpl_QueryInterface(
*/
static ULONG WINAPI EnumMonikerImpl_AddRef(LPENUMMONIKER iface)
{
EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
ULONG ref;
if (This == NULL) return E_POINTER;
@ -116,7 +118,7 @@ static ULONG WINAPI EnumMonikerImpl_AddRef(LPENUMMONIKER iface)
*/
static ULONG WINAPI EnumMonikerImpl_Release(LPENUMMONIKER iface)
{
EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
ULONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p)->() Release from %d\n", iface, ref + 1);
@ -139,7 +141,7 @@ static ULONG WINAPI EnumMonikerImpl_Release(LPENUMMONIKER iface)
static HRESULT WINAPI EnumMonikerImpl_Next(LPENUMMONIKER iface, ULONG celt, IMoniker ** rgelt, ULONG * pceltFetched)
{
ULONG fetched;
EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
TRACE("(%p)->(%d, %p, %p)\n", iface, celt, rgelt, pceltFetched);
@ -164,7 +166,7 @@ static HRESULT WINAPI EnumMonikerImpl_Next(LPENUMMONIKER iface, ULONG celt, IMon
static HRESULT WINAPI EnumMonikerImpl_Skip(LPENUMMONIKER iface, ULONG celt)
{
EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
TRACE("(%p)->(%d)\n", iface, celt);
@ -175,7 +177,7 @@ static HRESULT WINAPI EnumMonikerImpl_Skip(LPENUMMONIKER iface, ULONG celt)
static HRESULT WINAPI EnumMonikerImpl_Reset(LPENUMMONIKER iface)
{
EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
TRACE("(%p)->()\n", iface);

View file

@ -28,13 +28,18 @@ WINE_DEFAULT_DEBUG_CHANNEL(quartz);
typedef struct IEnumRegFiltersImpl
{
const IEnumRegFiltersVtbl * lpVtbl;
IEnumRegFilters IEnumRegFilters_iface;
LONG refCount;
ULONG size;
REGFILTER* RegFilters;
ULONG uIndex;
} IEnumRegFiltersImpl;
static inline IEnumRegFiltersImpl *impl_from_IEnumRegFilters(IEnumRegFilters *iface)
{
return CONTAINING_RECORD(iface, IEnumRegFiltersImpl, IEnumRegFilters_iface);
}
static const struct IEnumRegFiltersVtbl IEnumRegFiltersImpl_Vtbl;
HRESULT IEnumRegFiltersImpl_Construct(REGFILTER* pInRegFilters, const ULONG size, IEnumRegFilters ** ppEnum)
@ -79,13 +84,13 @@ HRESULT IEnumRegFiltersImpl_Construct(REGFILTER* pInRegFilters, const ULONG size
CopyMemory(pRegFilters[i].Name, pInRegFilters[i].Name, (strlenW(pInRegFilters[i].Name)+1)*sizeof(WCHAR));
}
pEnumRegFilters->lpVtbl = &IEnumRegFiltersImpl_Vtbl;
pEnumRegFilters->IEnumRegFilters_iface.lpVtbl = &IEnumRegFiltersImpl_Vtbl;
pEnumRegFilters->refCount = 1;
pEnumRegFilters->uIndex = 0;
pEnumRegFilters->RegFilters = pRegFilters;
pEnumRegFilters->size = size;
*ppEnum = (IEnumRegFilters *)(&pEnumRegFilters->lpVtbl);
*ppEnum = &pEnumRegFilters->IEnumRegFilters_iface;
return S_OK;
}
@ -114,7 +119,7 @@ static HRESULT WINAPI IEnumRegFiltersImpl_QueryInterface(IEnumRegFilters * iface
static ULONG WINAPI IEnumRegFiltersImpl_AddRef(IEnumRegFilters * iface)
{
IEnumRegFiltersImpl *This = (IEnumRegFiltersImpl *)iface;
IEnumRegFiltersImpl *This = impl_from_IEnumRegFilters(iface);
ULONG refCount = InterlockedIncrement(&This->refCount);
TRACE("(%p)\n", iface);
@ -124,7 +129,7 @@ static ULONG WINAPI IEnumRegFiltersImpl_AddRef(IEnumRegFilters * iface)
static ULONG WINAPI IEnumRegFiltersImpl_Release(IEnumRegFilters * iface)
{
IEnumRegFiltersImpl *This = (IEnumRegFiltersImpl *)iface;
IEnumRegFiltersImpl *This = impl_from_IEnumRegFilters(iface);
ULONG refCount = InterlockedDecrement(&This->refCount);
TRACE("(%p)\n", iface);
@ -147,7 +152,7 @@ static ULONG WINAPI IEnumRegFiltersImpl_Release(IEnumRegFilters * iface)
static HRESULT WINAPI IEnumRegFiltersImpl_Next(IEnumRegFilters * iface, ULONG cFilters, REGFILTER ** ppRegFilter, ULONG * pcFetched)
{
ULONG cFetched;
IEnumRegFiltersImpl *This = (IEnumRegFiltersImpl *)iface;
IEnumRegFiltersImpl *This = impl_from_IEnumRegFilters(iface);
unsigned int i;
cFetched = min(This->size, This->uIndex + cFilters) - This->uIndex;
@ -193,7 +198,7 @@ static HRESULT WINAPI IEnumRegFiltersImpl_Skip(IEnumRegFilters * iface, ULONG n)
static HRESULT WINAPI IEnumRegFiltersImpl_Reset(IEnumRegFilters * iface)
{
IEnumRegFiltersImpl *This = (IEnumRegFiltersImpl *)iface;
IEnumRegFiltersImpl *This = impl_from_IEnumRegFilters(iface);
TRACE("(%p)\n", iface);

View file

@ -0,0 +1,50 @@
/*
* Copyright (C) 2009 Vitaliy Margolen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
import "objidl.idl";
import "strmif.idl";
import "unknwn.idl";
/*****************************************************************************
* IAMFilterData interface
*
* Notes:
* - This interface is deprecated and IFilterMapper2 should be used instead.
* - There is no full replacement for IAMFilterData::ParseFilterData short of manually
* parsing out the REGFILTER2 struct from the binary blob.
*/
[
object,
uuid(97f7c4d4-547b-4a5f-8332-536430ad2e4d),
pointer_default(unique)
]
interface IAMFilterData : IUnknown
{
typedef [unique] IAMFilterData *LPIAMFILTERDATA;
HRESULT ParseFilterData(
[in] BYTE * rgbFilterData,
[in] ULONG cb,
[out] BYTE ** prgbRegFilter2);
HRESULT CreateFilterData(
[in] REGFILTER2 * prf2,
[out] BYTE ** prgbFilterData,
[out] ULONG * pcb);
}

View file

@ -39,37 +39,50 @@ static const WCHAR wszOutputPinName[] = { 'O','u','t','p','u','t',0 };
typedef struct AsyncReader
{
const IBaseFilterVtbl * lpVtbl;
const IFileSourceFilterVtbl * lpVtblFSF;
LONG refCount;
FILTER_INFO filterInfo;
FILTER_STATE state;
CRITICAL_SECTION csFilter;
DWORD lastpinchange;
BaseFilter filter;
IFileSourceFilter IFileSourceFilter_iface;
IAMFilterMiscFlags IAMFilterMiscFlags_iface;
IPin * pOutputPin;
LPOLESTR pszFileName;
AM_MEDIA_TYPE * pmt;
} AsyncReader;
static inline AsyncReader *impl_from_BaseFilter(BaseFilter *iface)
{
return CONTAINING_RECORD(iface, AsyncReader, filter);
}
static inline AsyncReader *impl_from_IBaseFilter(IBaseFilter *iface)
{
return CONTAINING_RECORD(iface, AsyncReader, filter.IBaseFilter_iface);
}
static inline AsyncReader *impl_from_IFileSourceFilter(IFileSourceFilter *iface)
{
return CONTAINING_RECORD(iface, AsyncReader, IFileSourceFilter_iface);
}
static inline AsyncReader *impl_from_IAMFilterMiscFlags(IAMFilterMiscFlags *iface)
{
return CONTAINING_RECORD(iface, AsyncReader, IAMFilterMiscFlags_iface);
}
static const IBaseFilterVtbl AsyncReader_Vtbl;
static const IFileSourceFilterVtbl FileSource_Vtbl;
static const IAsyncReaderVtbl FileAsyncReader_Vtbl;
static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl;
static HRESULT FileAsyncReader_Construct(HANDLE hFile, IBaseFilter * pBaseFilter, LPCRITICAL_SECTION pCritSec, IPin ** ppPin);
static inline AsyncReader *impl_from_IFileSourceFilter( IFileSourceFilter *iface )
{
return (AsyncReader *)((char*)iface - FIELD_OFFSET(AsyncReader, lpVtblFSF));
}
static WCHAR const mediatype_name[11] = {
static const WCHAR mediatype_name[] = {
'M', 'e', 'd', 'i', 'a', ' ', 'T', 'y', 'p', 'e', 0 };
static WCHAR const subtype_name[8] = {
static const WCHAR subtype_name[] = {
'S', 'u', 'b', 't', 'y', 'p', 'e', 0 };
static const WCHAR source_filter_name[] = {
'S','o','u','r','c','e',' ','F','i','l','t','e','r',0};
static HRESULT process_extensions(HKEY hkeyExtensions, LPCOLESTR pszFileName, GUID * majorType, GUID * minorType)
static HRESULT process_extensions(HKEY hkeyExtensions, LPCOLESTR pszFileName, GUID * majorType, GUID * minorType, GUID * sourceFilter)
{
WCHAR *extension;
LONG l;
@ -89,17 +102,31 @@ static HRESULT process_extensions(HKEY hkeyExtensions, LPCOLESTR pszFileName, GU
if (l)
return E_FAIL;
size = sizeof(keying);
l = RegQueryValueExW(hsub, mediatype_name, NULL, NULL, (LPBYTE)keying, &size);
if (!l)
CLSIDFromString(keying, majorType);
if (majorType)
{
size = sizeof(keying);
l = RegQueryValueExW(hsub, mediatype_name, NULL, NULL, (LPBYTE)keying, &size);
if (!l)
CLSIDFromString(keying, majorType);
}
size = sizeof(keying);
if (!l)
l = RegQueryValueExW(hsub, subtype_name, NULL, NULL, (LPBYTE)keying, &size);
if (minorType)
{
size = sizeof(keying);
if (!l)
l = RegQueryValueExW(hsub, subtype_name, NULL, NULL, (LPBYTE)keying, &size);
if (!l)
CLSIDFromString(keying, minorType);
}
if (!l)
CLSIDFromString(keying, minorType);
if (sourceFilter)
{
size = sizeof(keying);
if (!l)
l = RegQueryValueExW(hsub, source_filter_name, NULL, NULL, (LPBYTE)keying, &size);
if (!l)
CLSIDFromString(keying, sourceFilter);
}
RegCloseKey(hsub);
@ -183,8 +210,8 @@ static HRESULT process_pattern_string(LPCWSTR wszPatternString, IAsyncReader * p
if (!(wszPatternString = strchrW(wszPatternString, ',')))
hr = E_INVALIDARG;
wszPatternString++; /* skip ',' */
else
wszPatternString++; /* skip ',' */
}
if (hr == S_OK)
@ -227,7 +254,7 @@ static HRESULT process_pattern_string(LPCWSTR wszPatternString, IAsyncReader * p
return hr;
}
static HRESULT GetClassMediaFile(IAsyncReader * pReader, LPCOLESTR pszFileName, GUID * majorType, GUID * minorType)
HRESULT GetClassMediaFile(IAsyncReader * pReader, LPCOLESTR pszFileName, GUID * majorType, GUID * minorType, GUID * sourceFilter)
{
HKEY hkeyMediaType = NULL;
LONG lRet;
@ -237,8 +264,12 @@ static HRESULT GetClassMediaFile(IAsyncReader * pReader, LPCOLESTR pszFileName,
TRACE("(%p, %s, %p, %p)\n", pReader, debugstr_w(pszFileName), majorType, minorType);
*majorType = GUID_NULL;
*minorType = GUID_NULL;
if(majorType)
*majorType = GUID_NULL;
if(minorType)
*minorType = GUID_NULL;
if(sourceFilter)
*sourceFilter = GUID_NULL;
lRet = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszMediaType, 0, KEY_READ, &hkeyMediaType);
hr = HRESULT_FROM_WIN32(lRet);
@ -261,10 +292,11 @@ static HRESULT GetClassMediaFile(IAsyncReader * pReader, LPCOLESTR pszFileName,
TRACE("%s\n", debugstr_w(wszMajorKeyName));
if (!strcmpW(wszExtensions, wszMajorKeyName))
{
if (process_extensions(hkeyMajor, pszFileName, majorType, minorType) == S_OK)
if (process_extensions(hkeyMajor, pszFileName, majorType, minorType, sourceFilter) == S_OK)
bFound = TRUE;
}
else
/* We need a reader interface to check bytes */
else if (pReader)
{
DWORD indexMinor;
@ -273,6 +305,8 @@ static HRESULT GetClassMediaFile(IAsyncReader * pReader, LPCOLESTR pszFileName,
HKEY hkeyMinor;
WCHAR wszMinorKeyName[CHARS_IN_GUID];
DWORD dwMinorKeyNameLen = sizeof(wszMinorKeyName) / sizeof(wszMinorKeyName[0]);
WCHAR wszSourceFilterKeyName[CHARS_IN_GUID];
DWORD dwSourceFilterKeyNameLen = sizeof(wszSourceFilterKeyName);
DWORD maxValueLen;
DWORD indexValue;
@ -294,26 +328,37 @@ static HRESULT GetClassMediaFile(IAsyncReader * pReader, LPCOLESTR pszFileName,
LPWSTR wszPatternString = HeapAlloc(GetProcessHeap(), 0, maxValueLen);
DWORD dwValueNameLen = sizeof(wszValueName) / sizeof(wszValueName[0]); /* remember this is in chars */
DWORD dwDataLen = maxValueLen; /* remember this is in bytes */
static const WCHAR wszSourceFilter[] = {'S','o','u','r','c','e',' ','F','i','l','t','e','r',0};
LONG temp;
if ((temp = RegEnumValueW(hkeyMinor, indexValue, wszValueName, &dwValueNameLen, NULL, &dwType, (LPBYTE)wszPatternString, &dwDataLen)) != ERROR_SUCCESS)
if (RegEnumValueW(hkeyMinor, indexValue, wszValueName, &dwValueNameLen, NULL, &dwType, (LPBYTE)wszPatternString, &dwDataLen) != ERROR_SUCCESS)
{
HeapFree(GetProcessHeap(), 0, wszPatternString);
break;
}
/* if it is not the source filter value */
if (strcmpW(wszValueName, wszSourceFilter))
{
if (process_pattern_string(wszPatternString, pReader) == S_OK)
{
if (SUCCEEDED(CLSIDFromString(wszMajorKeyName, majorType)) &&
SUCCEEDED(CLSIDFromString(wszMinorKeyName, minorType)))
bFound = TRUE;
}
if (strcmpW(wszValueName, source_filter_name)==0) {
HeapFree(GetProcessHeap(), 0, wszPatternString);
continue;
}
HeapFree(GetProcessHeap(), 0, wszPatternString);
/* if it is not the source filter value */
if (process_pattern_string(wszPatternString, pReader) == S_OK)
{
HeapFree(GetProcessHeap(), 0, wszPatternString);
if (majorType && FAILED(CLSIDFromString(wszMajorKeyName, majorType)))
break;
if (minorType && FAILED(CLSIDFromString(wszMinorKeyName, minorType)))
break;
if (sourceFilter)
{
/* Look up the source filter key */
if (RegQueryValueExW(hkeyMinor, source_filter_name, NULL, NULL, (LPBYTE)wszSourceFilterKeyName, &dwSourceFilterKeyNameLen))
break;
if (FAILED(CLSIDFromString(wszSourceFilterKeyName, sourceFilter)))
break;
}
bFound = TRUE;
} else
HeapFree(GetProcessHeap(), 0, wszPatternString);
}
CloseHandle(hkeyMinor);
}
@ -329,11 +374,45 @@ static HRESULT GetClassMediaFile(IAsyncReader * pReader, LPCOLESTR pszFileName,
hr = E_FAIL;
}
else if (bFound)
TRACE("Found file's class: major = %s, subtype = %s\n", qzdebugstr_guid(majorType), qzdebugstr_guid(minorType));
{
TRACE("Found file's class:\n");
if(majorType)
TRACE("\tmajor = %s\n", qzdebugstr_guid(majorType));
if(minorType)
TRACE("\tsubtype = %s\n", qzdebugstr_guid(minorType));
if(sourceFilter)
TRACE("\tsource filter = %s\n", qzdebugstr_guid(sourceFilter));
}
return hr;
}
static IPin* WINAPI AsyncReader_GetPin(BaseFilter *iface, int pos)
{
AsyncReader *This = impl_from_BaseFilter(iface);
if (pos >= 1 || !This->pOutputPin)
return NULL;
IPin_AddRef(This->pOutputPin);
return This->pOutputPin;
}
static LONG WINAPI AsyncReader_GetPinCount(BaseFilter *iface)
{
AsyncReader *This = impl_from_BaseFilter(iface);
if (!This->pOutputPin)
return 0;
else
return 1;
}
static const BaseFilterFuncTable BaseFuncTable = {
AsyncReader_GetPin,
AsyncReader_GetPinCount
};
HRESULT AsyncReader_create(IUnknown * pUnkOuter, LPVOID * ppv)
{
AsyncReader *pAsyncRead;
@ -346,17 +425,11 @@ HRESULT AsyncReader_create(IUnknown * pUnkOuter, LPVOID * ppv)
if (!pAsyncRead)
return E_OUTOFMEMORY;
pAsyncRead->lpVtbl = &AsyncReader_Vtbl;
pAsyncRead->lpVtblFSF = &FileSource_Vtbl;
pAsyncRead->refCount = 1;
pAsyncRead->filterInfo.achName[0] = '\0';
pAsyncRead->filterInfo.pGraph = NULL;
pAsyncRead->pOutputPin = NULL;
pAsyncRead->lastpinchange = GetTickCount();
pAsyncRead->state = State_Stopped;
BaseFilter_Init(&pAsyncRead->filter, &AsyncReader_Vtbl, &CLSID_AsyncReader, (DWORD_PTR)(__FILE__ ": AsyncReader.csFilter"), &BaseFuncTable);
InitializeCriticalSection(&pAsyncRead->csFilter);
pAsyncRead->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": AsyncReader.csFilter");
pAsyncRead->IFileSourceFilter_iface.lpVtbl = &FileSource_Vtbl;
pAsyncRead->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_Vtbl;
pAsyncRead->pOutputPin = NULL;
pAsyncRead->pszFileName = NULL;
pAsyncRead->pmt = NULL;
@ -372,7 +445,7 @@ HRESULT AsyncReader_create(IUnknown * pUnkOuter, LPVOID * ppv)
static HRESULT WINAPI AsyncReader_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
{
AsyncReader *This = (AsyncReader *)iface;
AsyncReader *This = impl_from_IBaseFilter(iface);
TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv);
@ -387,7 +460,9 @@ static HRESULT WINAPI AsyncReader_QueryInterface(IBaseFilter * iface, REFIID rii
else if (IsEqualIID(riid, &IID_IBaseFilter))
*ppv = This;
else if (IsEqualIID(riid, &IID_IFileSourceFilter))
*ppv = &This->lpVtblFSF;
*ppv = &This->IFileSourceFilter_iface;
else if (IsEqualIID(riid, &IID_IAMFilterMiscFlags))
*ppv = &This->IAMFilterMiscFlags_iface;
if (*ppv)
{
@ -402,20 +477,10 @@ static HRESULT WINAPI AsyncReader_QueryInterface(IBaseFilter * iface, REFIID rii
return E_NOINTERFACE;
}
static ULONG WINAPI AsyncReader_AddRef(IBaseFilter * iface)
{
AsyncReader *This = (AsyncReader *)iface;
ULONG refCount = InterlockedIncrement(&This->refCount);
TRACE("(%p)->() AddRef from %d\n", This, refCount - 1);
return refCount;
}
static ULONG WINAPI AsyncReader_Release(IBaseFilter * iface)
{
AsyncReader *This = (AsyncReader *)iface;
ULONG refCount = InterlockedDecrement(&This->refCount);
AsyncReader *This = impl_from_IBaseFilter(iface);
ULONG refCount = BaseFilterImpl_Release(iface);
TRACE("(%p)->() Release from %d\n", This, refCount + 1);
@ -432,9 +497,6 @@ static ULONG WINAPI AsyncReader_Release(IBaseFilter * iface)
IPin_Disconnect(This->pOutputPin);
IPin_Release(This->pOutputPin);
}
This->csFilter.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&This->csFilter);
This->lpVtbl = NULL;
CoTaskMemFree(This->pszFileName);
if (This->pmt)
FreeMediaType(This->pmt);
@ -445,189 +507,100 @@ static ULONG WINAPI AsyncReader_Release(IBaseFilter * iface)
return refCount;
}
/** IPersist methods **/
static HRESULT WINAPI AsyncReader_GetClassID(IBaseFilter * iface, CLSID * pClsid)
{
TRACE("(%p)\n", pClsid);
*pClsid = CLSID_AsyncReader;
return S_OK;
}
/** IMediaFilter methods **/
static HRESULT WINAPI AsyncReader_Stop(IBaseFilter * iface)
{
AsyncReader *This = (AsyncReader *)iface;
AsyncReader *This = impl_from_IBaseFilter(iface);
TRACE("()\n");
This->state = State_Stopped;
This->filter.state = State_Stopped;
return S_OK;
}
static HRESULT WINAPI AsyncReader_Pause(IBaseFilter * iface)
{
AsyncReader *This = (AsyncReader *)iface;
AsyncReader *This = impl_from_IBaseFilter(iface);
TRACE("()\n");
This->state = State_Paused;
This->filter.state = State_Paused;
return S_OK;
}
static HRESULT WINAPI AsyncReader_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
{
AsyncReader *This = (AsyncReader *)iface;
AsyncReader *This = impl_from_IBaseFilter(iface);
TRACE("(%x%08x)\n", (ULONG)(tStart >> 32), (ULONG)tStart);
This->state = State_Running;
return S_OK;
}
static HRESULT WINAPI AsyncReader_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
{
AsyncReader *This = (AsyncReader *)iface;
TRACE("(%u, %p)\n", dwMilliSecsTimeout, pState);
*pState = This->state;
return S_OK;
}
static HRESULT WINAPI AsyncReader_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
{
/* AsyncReader *This = (AsyncReader *)iface;*/
TRACE("(%p)\n", pClock);
return S_OK;
}
static HRESULT WINAPI AsyncReader_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
{
/* AsyncReader *This = (AsyncReader *)iface;*/
TRACE("(%p)\n", ppClock);
This->filter.state = State_Running;
return S_OK;
}
/** IBaseFilter methods **/
static HRESULT AsyncReader_GetPin(IBaseFilter *iface, ULONG pos, IPin **pin, DWORD *lastsynctick)
{
AsyncReader *This = (AsyncReader *)iface;
/* Our pins are almost static, not changing so setting static tick count is ok */
*lastsynctick = This->lastpinchange;
if (pos >= 1 || !This->pOutputPin)
return S_FALSE;
*pin = This->pOutputPin;
IPin_AddRef(*pin);
return S_OK;
}
static HRESULT WINAPI AsyncReader_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
{
AsyncReader *This = (AsyncReader *)iface;
TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
return IEnumPinsImpl_Construct(ppEnum, AsyncReader_GetPin, iface);
}
static HRESULT WINAPI AsyncReader_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
{
FIXME("(%s, %p)\n", debugstr_w(Id), ppPin);
AsyncReader *This = impl_from_IBaseFilter(iface);
TRACE("(%s, %p)\n", debugstr_w(Id), ppPin);
return E_NOTIMPL;
}
if (!Id || !ppPin)
return E_POINTER;
static HRESULT WINAPI AsyncReader_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
{
AsyncReader *This = (AsyncReader *)iface;
if (strcmpW(Id, wszOutputPinName))
{
*ppPin = NULL;
return VFW_E_NOT_FOUND;
}
TRACE("(%p)\n", pInfo);
strcpyW(pInfo->achName, This->filterInfo.achName);
pInfo->pGraph = This->filterInfo.pGraph;
if (pInfo->pGraph)
IFilterGraph_AddRef(pInfo->pGraph);
*ppPin = This->pOutputPin;
IPin_AddRef(*ppPin);
return S_OK;
}
static HRESULT WINAPI AsyncReader_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName)
{
AsyncReader *This = (AsyncReader *)iface;
TRACE("(%p, %s)\n", pGraph, debugstr_w(pName));
if (pName)
strcpyW(This->filterInfo.achName, pName);
else
*This->filterInfo.achName = 0;
This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
return S_OK;
}
static HRESULT WINAPI AsyncReader_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo)
{
FIXME("(%p)\n", pVendorInfo);
return E_NOTIMPL;
}
static const IBaseFilterVtbl AsyncReader_Vtbl =
{
AsyncReader_QueryInterface,
AsyncReader_AddRef,
BaseFilterImpl_AddRef,
AsyncReader_Release,
AsyncReader_GetClassID,
BaseFilterImpl_GetClassID,
AsyncReader_Stop,
AsyncReader_Pause,
AsyncReader_Run,
AsyncReader_GetState,
AsyncReader_SetSyncSource,
AsyncReader_GetSyncSource,
AsyncReader_EnumPins,
BaseFilterImpl_GetState,
BaseFilterImpl_SetSyncSource,
BaseFilterImpl_GetSyncSource,
BaseFilterImpl_EnumPins,
AsyncReader_FindPin,
AsyncReader_QueryFilterInfo,
AsyncReader_JoinFilterGraph,
AsyncReader_QueryVendorInfo
BaseFilterImpl_QueryFilterInfo,
BaseFilterImpl_JoinFilterGraph,
BaseFilterImpl_QueryVendorInfo
};
static HRESULT WINAPI FileSource_QueryInterface(IFileSourceFilter * iface, REFIID riid, LPVOID * ppv)
{
AsyncReader *This = impl_from_IFileSourceFilter(iface);
return IBaseFilter_QueryInterface((IFileSourceFilter*)&This->lpVtbl, riid, ppv);
return IBaseFilter_QueryInterface(&This->filter.IBaseFilter_iface, riid, ppv);
}
static ULONG WINAPI FileSource_AddRef(IFileSourceFilter * iface)
{
AsyncReader *This = impl_from_IFileSourceFilter(iface);
return IBaseFilter_AddRef((IFileSourceFilter*)&This->lpVtbl);
return IBaseFilter_AddRef(&This->filter.IBaseFilter_iface);
}
static ULONG WINAPI FileSource_Release(IFileSourceFilter * iface)
{
AsyncReader *This = impl_from_IFileSourceFilter(iface);
return IBaseFilter_Release((IFileSourceFilter*)&This->lpVtbl);
return IBaseFilter_Release(&This->filter.IBaseFilter_iface);
}
static HRESULT WINAPI FileSource_Load(IFileSourceFilter * iface, LPCOLESTR pszFileName, const AM_MEDIA_TYPE * pmt)
@ -649,8 +622,8 @@ static HRESULT WINAPI FileSource_Load(IFileSourceFilter * iface, LPCOLESTR pszFi
}
/* create pin */
hr = FileAsyncReader_Construct(hFile, (IBaseFilter *)&This->lpVtbl, &This->csFilter, &This->pOutputPin);
This->lastpinchange = GetTickCount();
hr = FileAsyncReader_Construct(hFile, &This->filter.IBaseFilter_iface, &This->filter.csFilter, &This->pOutputPin);
BaseFilterImpl_IncrementPinVersion(&This->filter);
if (SUCCEEDED(hr))
hr = IPin_QueryInterface(This->pOutputPin, &IID_IAsyncReader, (LPVOID *)&pReader);
@ -675,7 +648,7 @@ static HRESULT WINAPI FileSource_Load(IFileSourceFilter * iface, LPCOLESTR pszFi
This->pmt->pUnk = NULL;
This->pmt->lSampleSize = 0;
This->pmt->formattype = FORMAT_None;
hr = GetClassMediaFile(pReader, pszFileName, &This->pmt->majortype, &This->pmt->subtype);
hr = GetClassMediaFile(pReader, pszFileName, &This->pmt->majortype, &This->pmt->subtype, NULL);
if (FAILED(hr))
{
CoTaskMemFree(This->pmt);
@ -759,9 +732,10 @@ typedef struct DATAREQUEST
typedef struct FileAsyncReader
{
OutputPin pin;
const struct IAsyncReaderVtbl * lpVtblAR;
BaseOutputPin pin;
IAsyncReader IAsyncReader_iface;
ALLOCATOR_PROPERTIES allocProps;
HANDLE hFile;
BOOL bFlushing;
/* Why would you need more? Every sample has its own handle */
@ -775,30 +749,62 @@ typedef struct FileAsyncReader
HANDLE *handle_list;
} FileAsyncReader;
static inline FileAsyncReader *impl_from_IAsyncReader( IAsyncReader *iface )
static inline FileAsyncReader *impl_from_IPin(IPin *iface)
{
return (FileAsyncReader *)((char*)iface - FIELD_OFFSET(FileAsyncReader, lpVtblAR));
return CONTAINING_RECORD(iface, FileAsyncReader, pin.pin.IPin_iface);
}
static HRESULT AcceptProcAFR(LPVOID iface, const AM_MEDIA_TYPE *pmt)
static inline FileAsyncReader *impl_from_BasePin(BasePin *iface)
{
AsyncReader *This = iface;
return CONTAINING_RECORD(iface, FileAsyncReader, pin.pin);
}
static inline FileAsyncReader *impl_from_BaseOutputPin(BaseOutputPin *iface)
{
return CONTAINING_RECORD(iface, FileAsyncReader, pin);
}
static inline BaseOutputPin *impl_BaseOututPin_from_BasePin(BasePin *iface)
{
return CONTAINING_RECORD(iface, BaseOutputPin, pin);
}
static inline FileAsyncReader *impl_from_IAsyncReader(IAsyncReader *iface)
{
return CONTAINING_RECORD(iface, FileAsyncReader, IAsyncReader_iface);
}
static HRESULT WINAPI FileAsyncReaderPin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *pmt)
{
FileAsyncReader *This = impl_from_IPin(iface);
AM_MEDIA_TYPE *pmt_filter = impl_from_IBaseFilter(This->pin.pin.pinInfo.pFilter)->pmt;
FIXME("(%p, %p)\n", iface, pmt);
if (IsEqualGUID(&pmt->majortype, &This->pmt->majortype) &&
IsEqualGUID(&pmt->subtype, &This->pmt->subtype) &&
if (IsEqualGUID(&pmt->majortype, &pmt_filter->majortype) &&
IsEqualGUID(&pmt->subtype, &pmt_filter->subtype) &&
IsEqualGUID(&pmt->formattype, &FORMAT_None))
return S_OK;
return S_FALSE;
}
static HRESULT WINAPI FileAsyncReaderPin_GetMediaType(BasePin *iface, int iPosition, AM_MEDIA_TYPE *pmt)
{
FileAsyncReader *This = impl_from_BasePin(iface);
if (iPosition < 0)
return E_INVALIDARG;
if (iPosition > 0)
return VFW_S_NO_MORE_ITEMS;
CopyMediaType(pmt, impl_from_IBaseFilter(This->pin.pin.pinInfo.pFilter)->pmt);
return S_OK;
}
/* overridden pin functions */
static HRESULT WINAPI FileAsyncReaderPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv)
{
FileAsyncReader *This = (FileAsyncReader *)iface;
FileAsyncReader *This = impl_from_IPin(iface);
TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv);
*ppv = NULL;
@ -808,7 +814,7 @@ static HRESULT WINAPI FileAsyncReaderPin_QueryInterface(IPin * iface, REFIID rii
else if (IsEqualIID(riid, &IID_IPin))
*ppv = This;
else if (IsEqualIID(riid, &IID_IAsyncReader))
*ppv = &This->lpVtblAR;
*ppv = &This->IAsyncReader_iface;
if (*ppv)
{
@ -824,7 +830,7 @@ static HRESULT WINAPI FileAsyncReaderPin_QueryInterface(IPin * iface, REFIID rii
static ULONG WINAPI FileAsyncReaderPin_Release(IPin * iface)
{
FileAsyncReader *This = (FileAsyncReader *)iface;
FileAsyncReader *This = impl_from_IPin(iface);
ULONG refCount = InterlockedDecrement(&This->pin.pin.refCount);
int x;
@ -848,48 +854,35 @@ static ULONG WINAPI FileAsyncReaderPin_Release(IPin * iface)
return refCount;
}
static HRESULT WINAPI FileAsyncReaderPin_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum)
{
ENUMMEDIADETAILS emd;
FileAsyncReader *This = (FileAsyncReader *)iface;
TRACE("(%p)\n", ppEnum);
emd.cMediaTypes = 1;
emd.pMediaTypes = ((AsyncReader *)This->pin.pin.pinInfo.pFilter)->pmt;
return IEnumMediaTypesImpl_Construct(&emd, ppEnum);
}
static const IPinVtbl FileAsyncReaderPin_Vtbl =
{
FileAsyncReaderPin_QueryInterface,
IPinImpl_AddRef,
BasePinImpl_AddRef,
FileAsyncReaderPin_Release,
OutputPin_Connect,
OutputPin_ReceiveConnection,
IPinImpl_Disconnect,
IPinImpl_ConnectedTo,
IPinImpl_ConnectionMediaType,
IPinImpl_QueryPinInfo,
IPinImpl_QueryDirection,
IPinImpl_QueryId,
IPinImpl_QueryAccept,
FileAsyncReaderPin_EnumMediaTypes,
IPinImpl_QueryInternalConnections,
OutputPin_EndOfStream,
OutputPin_BeginFlush,
OutputPin_EndFlush,
OutputPin_NewSegment
BaseOutputPinImpl_Connect,
BaseOutputPinImpl_ReceiveConnection,
BasePinImpl_Disconnect,
BasePinImpl_ConnectedTo,
BasePinImpl_ConnectionMediaType,
BasePinImpl_QueryPinInfo,
BasePinImpl_QueryDirection,
BasePinImpl_QueryId,
FileAsyncReaderPin_QueryAccept,
BasePinImpl_EnumMediaTypes,
BasePinImpl_QueryInternalConnections,
BaseOutputPinImpl_EndOfStream,
BaseOutputPinImpl_BeginFlush,
BaseOutputPinImpl_EndFlush,
BasePinImpl_NewSegment
};
/* Function called as a helper to IPin_Connect */
/* specific AM_MEDIA_TYPE - it cannot be NULL */
/* this differs from standard OutputPin_ConnectSpecific only in that it
/* this differs from standard OutputPin_AttemptConnection only in that it
* doesn't need the IMemInputPin interface on the receiving pin */
static HRESULT FileAsyncReaderPin_ConnectSpecific(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
static HRESULT WINAPI FileAsyncReaderPin_AttemptConnection(BasePin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
{
OutputPin *This = (OutputPin *)iface;
BaseOutputPin *This = impl_BaseOututPin_from_BasePin(iface);
HRESULT hr;
TRACE("(%p, %p)\n", pReceivePin, pmt);
@ -901,7 +894,7 @@ static HRESULT FileAsyncReaderPin_ConnectSpecific(IPin * iface, IPin * pReceiveP
IPin_AddRef(pReceivePin);
CopyMediaType(&This->pin.mtCurrent, pmt);
hr = IPin_ReceiveConnection(pReceivePin, iface, pmt);
hr = IPin_ReceiveConnection(pReceivePin, &iface->IPin_iface, pmt);
if (FAILED(hr))
{
@ -914,6 +907,36 @@ static HRESULT FileAsyncReaderPin_ConnectSpecific(IPin * iface, IPin * pReceiveP
return hr;
}
static HRESULT WINAPI FileAsyncReaderPin_DecideBufferSize(BaseOutputPin *iface, IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest)
{
FileAsyncReader *This = impl_from_BaseOutputPin(iface);
ALLOCATOR_PROPERTIES actual;
if (ppropInputRequest->cbAlign && ppropInputRequest->cbAlign != This->allocProps.cbAlign)
FIXME("Requested Buffer cbAlign mismatch %i,%i\n",This->allocProps.cbAlign, ppropInputRequest->cbAlign);
if (ppropInputRequest->cbPrefix)
FIXME("Requested Buffer cbPrefix mismatch %i,%i\n",This->allocProps.cbPrefix, ppropInputRequest->cbPrefix);
if (ppropInputRequest->cbBuffer)
FIXME("Requested Buffer cbBuffer mismatch %i,%i\n",This->allocProps.cbBuffer, ppropInputRequest->cbBuffer);
if (ppropInputRequest->cBuffers)
FIXME("Requested Buffer cBuffers mismatch %i,%i\n",This->allocProps.cBuffers, ppropInputRequest->cBuffers);
return IMemAllocator_SetProperties(pAlloc, &This->allocProps, &actual);
}
static const BasePinFuncTable output_BaseFuncTable = {
NULL,
FileAsyncReaderPin_AttemptConnection,
BasePinImpl_GetMediaTypeVersion,
FileAsyncReaderPin_GetMediaType
};
static const BaseOutputPinFuncTable output_BaseOutputFuncTable = {
FileAsyncReaderPin_DecideBufferSize,
BaseOutputPinImpl_DecideAllocator,
BaseOutputPinImpl_BreakConnect
};
static HRESULT FileAsyncReader_Construct(HANDLE hFile, IBaseFilter * pBaseFilter, LPCRITICAL_SECTION pCritSec, IPin ** ppPin)
{
PIN_INFO piOutput;
@ -923,18 +946,17 @@ static HRESULT FileAsyncReader_Construct(HANDLE hFile, IBaseFilter * pBaseFilter
piOutput.dir = PINDIR_OUTPUT;
piOutput.pFilter = pBaseFilter;
strcpyW(piOutput.achName, wszOutputPinName);
hr = OutputPin_Construct(&FileAsyncReaderPin_Vtbl, sizeof(FileAsyncReader), &piOutput, NULL, pBaseFilter, AcceptProcAFR, pCritSec, ppPin);
hr = BaseOutputPin_Construct(&FileAsyncReaderPin_Vtbl, sizeof(FileAsyncReader), &piOutput, &output_BaseFuncTable, &output_BaseOutputFuncTable, pCritSec, ppPin);
if (SUCCEEDED(hr))
{
FileAsyncReader *pPinImpl = (FileAsyncReader *)*ppPin;
pPinImpl->lpVtblAR = &FileAsyncReader_Vtbl;
pPinImpl->IAsyncReader_iface.lpVtbl = &FileAsyncReader_Vtbl;
pPinImpl->hFile = hFile;
pPinImpl->bFlushing = FALSE;
pPinImpl->sample_list = NULL;
pPinImpl->handle_list = NULL;
pPinImpl->queued_number = 0;
pPinImpl->pin.pConnectSpecific = FileAsyncReaderPin_ConnectSpecific;
InitializeCriticalSection(&pPinImpl->csList);
pPinImpl->csList.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": FileAsyncReader.csList");
}
@ -947,21 +969,21 @@ static HRESULT WINAPI FileAsyncReader_QueryInterface(IAsyncReader * iface, REFII
{
FileAsyncReader *This = impl_from_IAsyncReader(iface);
return IPin_QueryInterface((IPin *)This, riid, ppv);
return IPin_QueryInterface(&This->pin.pin.IPin_iface, riid, ppv);
}
static ULONG WINAPI FileAsyncReader_AddRef(IAsyncReader * iface)
{
FileAsyncReader *This = impl_from_IAsyncReader(iface);
return IPin_AddRef((IPin *)This);
return IPin_AddRef(&This->pin.pin.IPin_iface);
}
static ULONG WINAPI FileAsyncReader_Release(IAsyncReader * iface)
{
FileAsyncReader *This = impl_from_IAsyncReader(iface);
return IPin_Release((IPin *)This);
return IPin_Release(&This->pin.pin.IPin_iface);
}
#define DEF_ALIGNMENT 1
@ -1034,7 +1056,7 @@ done:
This->handle_list[This->samples + 1 + x] = This->handle_list[x];
}
This->handle_list[This->samples] = CreateEventW(NULL, 1, 0, NULL);
This->pin.allocProps = *pProps;
This->allocProps = *pProps;
}
else
{
@ -1113,8 +1135,8 @@ static HRESULT WINAPI FileAsyncReader_Request(IAsyncReader * iface, IMediaSample
pDataRq = This->sample_list + x;
pDataRq->ovl.Offset = (DWORD) BYTES_FROM_MEDIATIME(Start);
pDataRq->ovl.OffsetHigh = (DWORD)(BYTES_FROM_MEDIATIME(Start) >> (sizeof(DWORD) * 8));
pDataRq->ovl.u.s.Offset = (DWORD) BYTES_FROM_MEDIATIME(Start);
pDataRq->ovl.u.s.OffsetHigh = (DWORD)(BYTES_FROM_MEDIATIME(Start) >> (sizeof(DWORD) * 8));
pDataRq->dwUserData = dwUser;
/* we violate traditional COM rules here by maintaining
@ -1239,7 +1261,7 @@ static HRESULT WINAPI FileAsyncReader_WaitForNext(IAsyncReader * iface, DWORD dw
/* Set the time on the sample */
IMediaSample_SetActualDataLength(pDataRq->pSample, dwBytes);
rtStart = (DWORD64)pDataRq->ovl.Offset + ((DWORD64)pDataRq->ovl.OffsetHigh << 32);
rtStart = (DWORD64)pDataRq->ovl.u.s.Offset + ((DWORD64)pDataRq->ovl.u.s.OffsetHigh << 32);
rtStart = MEDIATIME_FROM_BYTES(rtStart);
rtStop = rtStart + MEDIATIME_FROM_BYTES(dwBytes);
@ -1317,8 +1339,8 @@ static HRESULT WINAPI FileAsyncReader_SyncRead(IAsyncReader * iface, LONGLONG ll
ovl.hEvent = CreateEventW(NULL, 0, 0, NULL);
/* NOTE: llPosition is the actual byte position to start reading from */
ovl.Offset = (DWORD) llPosition;
ovl.OffsetHigh = (DWORD) (llPosition >> (sizeof(DWORD) * 8));
ovl.u.s.Offset = (DWORD) llPosition;
ovl.u.s.OffsetHigh = (DWORD) (llPosition >> (sizeof(DWORD) * 8));
if (!ReadFile(This->hFile, pBuffer, lLength, NULL, &ovl))
hr = HRESULT_FROM_WIN32(GetLastError());
@ -1406,3 +1428,30 @@ static const IAsyncReaderVtbl FileAsyncReader_Vtbl =
FileAsyncReader_BeginFlush,
FileAsyncReader_EndFlush,
};
static HRESULT WINAPI AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid, void **ppv) {
AsyncReader *This = impl_from_IAMFilterMiscFlags(iface);
return IUnknown_QueryInterface((IUnknown*)This, riid, ppv);
}
static ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface) {
AsyncReader *This = impl_from_IAMFilterMiscFlags(iface);
return IUnknown_AddRef((IUnknown*)This);
}
static ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface) {
AsyncReader *This = impl_from_IAMFilterMiscFlags(iface);
return IUnknown_Release((IUnknown*)This);
}
static ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface) {
return AM_FILTER_MISC_FLAGS_IS_SOURCE;
}
static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = {
AMFilterMiscFlags_QueryInterface,
AMFilterMiscFlags_AddRef,
AMFilterMiscFlags_Release,
AMFilterMiscFlags_GetMiscFlags
};

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
/*
* IFilterMapper & IFilterMapper2 Implementations
* IFilterMapper & IFilterMapper3 Implementations
*
* Copyright 2003 Robert Shearman
* Copyright 2004 Christian Costa
@ -19,8 +19,6 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
//#include <stdarg.h>
//#include "windef.h"
@ -36,6 +34,8 @@
//#include "strmif.h"
#include <wine/unicode.h>
//#include "uuids.h"
#include <initguid.h>
#include <fil_data.h>
#include <wine/debug.h>
@ -43,79 +43,34 @@ WINE_DEFAULT_DEBUG_CHANNEL(quartz);
#define ARRAYSIZE(array) (sizeof(array)/sizeof((array)[0]))
/* Unexposed IAMFilterData interface */
typedef struct IAMFilterData IAMFilterData;
typedef struct IAMFilterDataVtbl
typedef struct FilterMapper3Impl
{
BEGIN_INTERFACE
IUnknown IUnknown_inner;
IFilterMapper3 IFilterMapper3_iface;
IFilterMapper IFilterMapper_iface;
IAMFilterData IAMFilterData_iface;
IUnknown *outer_unk;
LONG ref;
} FilterMapper3Impl;
/*** IUnknown methods ***/
HRESULT (STDMETHODCALLTYPE *QueryInterface)(
IAMFilterData *This,
REFIID riid,
void **ppvObject);
ULONG (STDMETHODCALLTYPE *AddRef)(
IAMFilterData *This);
ULONG (STDMETHODCALLTYPE *Release)(
IAMFilterData *This);
/*** IAMFilterData methods ***/
HRESULT (STDMETHODCALLTYPE *ParseFilterData)(
IAMFilterData *This,
BYTE *pData,
ULONG cb,
BYTE **ppRegFilter2);
HRESULT (STDMETHODCALLTYPE *CreateFilterData)(
IAMFilterData* This,
REGFILTER2 *prf2,
BYTE **pRegFilterData,
ULONG *pcb);
END_INTERFACE
} IAMFilterDataVtbl;
struct IAMFilterData
static inline FilterMapper3Impl *impl_from_IFilterMapper3( IFilterMapper3 *iface )
{
const IAMFilterDataVtbl *lpVtbl;
};
static const GUID IID_IAMFilterData = {
0x97f7c4d4, 0x547b, 0x4a5f, { 0x83,0x32, 0x53,0x64,0x30,0xad,0x2e,0x4d }
};
typedef struct FilterMapper2Impl
{
const IFilterMapper2Vtbl *lpVtbl;
const IFilterMapperVtbl *lpVtblFilterMapper;
const IAMFilterDataVtbl *lpVtblAMFilterData;
const IUnknownVtbl *IInner_vtbl;
LONG refCount;
IUnknown * pUnkOuter;
BOOL bUnkOuterValid;
BOOL bAggregatable;
} FilterMapper2Impl;
static const IUnknownVtbl IInner_VTable;
static const IFilterMapper2Vtbl fm2vtbl;
static const IFilterMapperVtbl fmvtbl;
static const IAMFilterDataVtbl AMFilterDataVtbl;
static inline FilterMapper2Impl *impl_from_IFilterMapper( IFilterMapper *iface )
{
return (FilterMapper2Impl *)((char*)iface - FIELD_OFFSET(FilterMapper2Impl, lpVtblFilterMapper));
return CONTAINING_RECORD(iface, FilterMapper3Impl, IFilterMapper3_iface);
}
static inline FilterMapper2Impl *impl_from_IAMFilterData( IAMFilterData *iface )
static inline FilterMapper3Impl *impl_from_IFilterMapper( IFilterMapper *iface )
{
return (FilterMapper2Impl *)((char*)iface - FIELD_OFFSET(FilterMapper2Impl, lpVtblAMFilterData));
return CONTAINING_RECORD(iface, FilterMapper3Impl, IFilterMapper_iface);
}
static inline FilterMapper2Impl *impl_from_inner_IUnknown( IUnknown *iface )
static inline FilterMapper3Impl *impl_from_IAMFilterData( IAMFilterData *iface )
{
return (FilterMapper2Impl *)((char*)iface - FIELD_OFFSET(FilterMapper2Impl, IInner_vtbl));
return CONTAINING_RECORD(iface, FilterMapper3Impl, IAMFilterData_iface);
}
static inline FilterMapper3Impl *impl_from_IUnknown( IUnknown *iface )
{
return CONTAINING_RECORD(iface, FilterMapper3Impl, IUnknown_inner);
}
static const WCHAR wszClsidSlash[] = {'C','L','S','I','D','\\',0};
@ -218,68 +173,23 @@ static void delete_vector(struct Vector * v)
v->capacity = 0;
}
HRESULT FilterMapper2_create(IUnknown *pUnkOuter, LPVOID *ppObj)
{
FilterMapper2Impl * pFM2impl;
TRACE("(%p, %p)\n", pUnkOuter, ppObj);
pFM2impl = CoTaskMemAlloc(sizeof(*pFM2impl));
if (!pFM2impl)
return E_OUTOFMEMORY;
pFM2impl->pUnkOuter = pUnkOuter;
pFM2impl->bUnkOuterValid = FALSE;
pFM2impl->bAggregatable = FALSE;
pFM2impl->IInner_vtbl = &IInner_VTable;
pFM2impl->lpVtbl = &fm2vtbl;
pFM2impl->lpVtblFilterMapper = &fmvtbl;
pFM2impl->lpVtblAMFilterData = &AMFilterDataVtbl;
pFM2impl->refCount = 1;
*ppObj = pFM2impl;
TRACE("-- created at %p\n", pFM2impl);
return S_OK;
}
HRESULT FilterMapper_create(IUnknown *pUnkOuter, LPVOID *ppObj)
{
FilterMapper2Impl *pFM2impl;
HRESULT hr;
TRACE("(%p, %p)\n", pUnkOuter, ppObj);
hr = FilterMapper2_create(pUnkOuter, (LPVOID*)&pFM2impl);
if (FAILED(hr))
return hr;
*ppObj = &pFM2impl->lpVtblFilterMapper;
return hr;
}
/*** IUnknown (inner) methods ***/
static HRESULT WINAPI Inner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv)
static HRESULT WINAPI Inner_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
{
FilterMapper2Impl *This = impl_from_inner_IUnknown(iface);
FilterMapper3Impl *This = impl_from_IUnknown(iface);
TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
if (This->bAggregatable)
This->bUnkOuterValid = TRUE;
*ppv = NULL;
if (IsEqualIID(riid, &IID_IUnknown))
*ppv = &This->IInner_vtbl;
else if (IsEqualIID(riid, &IID_IFilterMapper2))
*ppv = This;
*ppv = &This->IUnknown_inner;
else if (IsEqualIID(riid, &IID_IFilterMapper2) || IsEqualIID(riid, &IID_IFilterMapper3))
*ppv = &This->IFilterMapper3_iface;
else if (IsEqualIID(riid, &IID_IFilterMapper))
*ppv = &This->lpVtblFilterMapper;
*ppv = &This->IFilterMapper_iface;
else if (IsEqualIID(riid, &IID_IAMFilterData))
*ppv = &This->lpVtblAMFilterData;
*ppv = &This->IAMFilterData_iface;
if (*ppv != NULL)
{
@ -291,29 +201,27 @@ static HRESULT WINAPI Inner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID
return E_NOINTERFACE;
}
static ULONG WINAPI Inner_AddRef(IUnknown * iface)
static ULONG WINAPI Inner_AddRef(IUnknown *iface)
{
FilterMapper2Impl *This = impl_from_inner_IUnknown(iface);
ULONG refCount = InterlockedIncrement(&This->refCount);
FilterMapper3Impl *This = impl_from_IUnknown(iface);
ULONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p)->() AddRef from %d\n", This, refCount - 1);
TRACE("(%p)->(): new ref = %d\n", This, ref);
return refCount;
return ref;
}
static ULONG WINAPI Inner_Release(IUnknown * iface)
static ULONG WINAPI Inner_Release(IUnknown *iface)
{
FilterMapper2Impl *This = impl_from_inner_IUnknown(iface);
ULONG refCount = InterlockedDecrement(&This->refCount);
FilterMapper3Impl *This = impl_from_IUnknown(iface);
ULONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p)->() Release from %d\n", This, refCount + 1);
TRACE("(%p)->(): new ref = %d\n", This, ref);
if (refCount == 0)
{
if (ref == 0)
CoTaskMemFree(This);
return 0;
}
return refCount;
return ref;
}
static const IUnknownVtbl IInner_VTable =
@ -323,58 +231,31 @@ static const IUnknownVtbl IInner_VTable =
Inner_Release
};
static HRESULT WINAPI FilterMapper2_QueryInterface(IFilterMapper2 * iface, REFIID riid, LPVOID *ppv)
static HRESULT WINAPI FilterMapper3_QueryInterface(IFilterMapper3 * iface, REFIID riid, LPVOID *ppv)
{
FilterMapper2Impl *This = (FilterMapper2Impl *)iface;
FilterMapper3Impl *This = impl_from_IFilterMapper3(iface);
if (This->bAggregatable)
This->bUnkOuterValid = TRUE;
if (This->pUnkOuter)
{
if (This->bAggregatable)
return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv);
if (IsEqualIID(riid, &IID_IUnknown))
{
HRESULT hr;
IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
This->bAggregatable = TRUE;
return hr;
}
*ppv = NULL;
return E_NOINTERFACE;
}
return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
}
static ULONG WINAPI FilterMapper2_AddRef(IFilterMapper2 * iface)
static ULONG WINAPI FilterMapper3_AddRef(IFilterMapper3 * iface)
{
FilterMapper2Impl *This = (FilterMapper2Impl *)iface;
FilterMapper3Impl *This = impl_from_IFilterMapper3(iface);
if (This->pUnkOuter && This->bUnkOuterValid)
return IUnknown_AddRef(This->pUnkOuter);
return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
return IUnknown_AddRef(This->outer_unk);
}
static ULONG WINAPI FilterMapper2_Release(IFilterMapper2 * iface)
static ULONG WINAPI FilterMapper3_Release(IFilterMapper3 * iface)
{
FilterMapper2Impl *This = (FilterMapper2Impl *)iface;
FilterMapper3Impl *This = impl_from_IFilterMapper3(iface);
if (This->pUnkOuter && This->bUnkOuterValid)
return IUnknown_Release(This->pUnkOuter);
return IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
return IUnknown_Release(This->outer_unk);
}
/*** IFilterMapper2 methods ***/
/*** IFilterMapper3 methods ***/
static HRESULT WINAPI FilterMapper2_CreateCategory(
IFilterMapper2 * iface,
static HRESULT WINAPI FilterMapper3_CreateCategory(
IFilterMapper3 * iface,
REFCLSID clsidCategory,
DWORD dwCategoryMerit,
LPCWSTR szDescription)
@ -431,8 +312,8 @@ static HRESULT WINAPI FilterMapper2_CreateCategory(
return hr;
}
static HRESULT WINAPI FilterMapper2_UnregisterFilter(
IFilterMapper2 * iface,
static HRESULT WINAPI FilterMapper3_UnregisterFilter(
IFilterMapper3 * iface,
const CLSID *pclsidCategory,
const OLECHAR *szInstance,
REFCLSID Filter)
@ -520,24 +401,24 @@ static HRESULT FM2_WriteFilterData(const REGFILTER2 * prf2, BYTE **ppData, ULONG
rrf.dwVersion = prf2->dwVersion;
rrf.dwMerit = prf2->dwMerit;
rrf.dwPins = prf2->u.s1.cPins2;
rrf.dwPins = prf2->cPins2;
rrf.dwUnused = 0;
add_data(&mainStore, (LPBYTE)&rrf, sizeof(rrf));
for (i = 0; i < prf2->u.s1.cPins2; i++)
for (i = 0; i < prf2->cPins2; i++)
{
size += sizeof(struct REG_RFP);
if (prf2->u.s1.rgPins2[i].clsPinCategory)
if (prf2->rgPins2[i].clsPinCategory)
size += sizeof(DWORD);
size += prf2->u.s1.rgPins2[i].nMediaTypes * sizeof(struct REG_TYPE);
size += prf2->u.s1.rgPins2[i].nMediums * sizeof(DWORD);
size += prf2->rgPins2[i].nMediaTypes * sizeof(struct REG_TYPE);
size += prf2->rgPins2[i].nMediums * sizeof(DWORD);
}
for (i = 0; i < prf2->u.s1.cPins2; i++)
for (i = 0; i < prf2->cPins2; i++)
{
struct REG_RFP rrfp;
REGFILTERPINS2 rgPin2 = prf2->u.s1.rgPins2[i];
REGFILTERPINS2 rgPin2 = prf2->rgPins2[i];
unsigned int j;
rrfp.signature[0] = '0';
@ -639,9 +520,9 @@ static HRESULT FM2_ReadFilterData(BYTE *pData, REGFILTER2 * prf2)
prf2->dwVersion = prrf->dwVersion;
prf2->dwMerit = prrf->dwMerit;
prf2->u.s1.cPins2 = prrf->dwPins;
prf2->cPins2 = prrf->dwPins;
rgPins2 = CoTaskMemAlloc(prrf->dwPins * sizeof(*rgPins2));
prf2->u.s1.rgPins2 = rgPins2;
prf2->rgPins2 = rgPins2;
pCurrent += sizeof(struct REG_RF);
for (i = 0; i < prrf->dwPins; i++)
@ -723,25 +604,25 @@ static HRESULT FM2_ReadFilterData(BYTE *pData, REGFILTER2 * prf2)
static void FM2_DeleteRegFilter(REGFILTER2 * prf2)
{
UINT i;
for (i = 0; i < prf2->u.s1.cPins2; i++)
for (i = 0; i < prf2->cPins2; i++)
{
UINT j;
if (prf2->u.s1.rgPins2[i].clsPinCategory)
CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2[i].clsPinCategory);
if (prf2->rgPins2[i].clsPinCategory)
CoTaskMemFree((LPVOID)prf2->rgPins2[i].clsPinCategory);
for (j = 0; j < prf2->u.s1.rgPins2[i].nMediaTypes; j++)
for (j = 0; j < prf2->rgPins2[i].nMediaTypes; j++)
{
CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2[i].lpMediaType[j].clsMajorType);
CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2[i].lpMediaType[j].clsMinorType);
CoTaskMemFree((LPVOID)prf2->rgPins2[i].lpMediaType[j].clsMajorType);
CoTaskMemFree((LPVOID)prf2->rgPins2[i].lpMediaType[j].clsMinorType);
}
CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2[i].lpMediaType);
CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2[i].lpMedium);
CoTaskMemFree((LPVOID)prf2->rgPins2[i].lpMediaType);
CoTaskMemFree((LPVOID)prf2->rgPins2[i].lpMedium);
}
CoTaskMemFree((LPVOID)prf2->u.s1.rgPins2);
CoTaskMemFree((LPVOID)prf2->rgPins2);
}
static HRESULT WINAPI FilterMapper2_RegisterFilter(
IFilterMapper2 * iface,
static HRESULT WINAPI FilterMapper3_RegisterFilter(
IFilterMapper3 * iface,
REFCLSID clsidFilter,
LPCWSTR szName,
IMoniker **ppMoniker,
@ -782,24 +663,24 @@ static HRESULT WINAPI FilterMapper2_RegisterFilter(
/* REGFILTER2 structure is converted from version 1 to 2. Tested on Win2k. */
regfilter2.dwVersion = 2;
regfilter2.dwMerit = prf2->dwMerit;
regfilter2.u.s1.cPins2 = prf2->u.s.cPins;
pregfp2 = CoTaskMemAlloc(prf2->u.s.cPins * sizeof(REGFILTERPINS2));
regfilter2.u.s1.rgPins2 = pregfp2;
for (i = 0; i < prf2->u.s.cPins; i++)
regfilter2.cPins2 = prf2->cPins;
pregfp2 = CoTaskMemAlloc(prf2->cPins * sizeof(REGFILTERPINS2));
regfilter2.rgPins2 = pregfp2;
for (i = 0; i < prf2->cPins; i++)
{
flags = 0;
if (prf2->u.s.rgPins[i].bRendered)
if (prf2->rgPins[i].bRendered)
flags |= REG_PINFLAG_B_RENDERER;
if (prf2->u.s.rgPins[i].bOutput)
if (prf2->rgPins[i].bOutput)
flags |= REG_PINFLAG_B_OUTPUT;
if (prf2->u.s.rgPins[i].bZero)
if (prf2->rgPins[i].bZero)
flags |= REG_PINFLAG_B_ZERO;
if (prf2->u.s.rgPins[i].bMany)
if (prf2->rgPins[i].bMany)
flags |= REG_PINFLAG_B_MANY;
pregfp2[i].dwFlags = flags;
pregfp2[i].cInstances = 1;
pregfp2[i].nMediaTypes = prf2->u.s.rgPins[i].nMediaTypes;
pregfp2[i].lpMediaType = prf2->u.s.rgPins[i].lpMediaType;
pregfp2[i].nMediaTypes = prf2->rgPins[i].nMediaTypes;
pregfp2[i].lpMediaType = prf2->rgPins[i].lpMediaType;
pregfp2[i].nMediums = 0;
pregfp2[i].lpMedium = NULL;
pregfp2[i].clsPinCategory = NULL;
@ -992,8 +873,8 @@ static int mm_compare(const void * left, const void * right)
* meaning match any input/output pin as long as one exists), otherwise match any
* filter that meets the rest of the requirements.
*/
static HRESULT WINAPI FilterMapper2_EnumMatchingFilters(
IFilterMapper2 * iface,
static HRESULT WINAPI FilterMapper3_EnumMatchingFilters(
IFilterMapper3 * iface,
IEnumMoniker **ppEnum,
DWORD dwFlags,
BOOL bExactMatch,
@ -1141,9 +1022,9 @@ static HRESULT WINAPI FilterMapper2_EnumMatchingFilters(
/* determine whether filter meets requirements */
if (SUCCEEDED(hrSub) && (rf2.dwMerit >= dwMerit))
{
for (i = 0; (i < rf2.u.s1.cPins2) && (!bInputMatch || !bOutputMatch); i++)
for (i = 0; (i < rf2.cPins2) && (!bInputMatch || !bOutputMatch); i++)
{
const REGFILTERPINS2 * rfp2 = rf2.u.s1.rgPins2 + i;
const REGFILTERPINS2 * rfp2 = rf2.rgPins2 + i;
bInputMatch = bInputMatch || (!(rfp2->dwFlags & REG_PINFLAG_B_OUTPUT) &&
(!bRender || (rfp2->dwFlags & REG_PINFLAG_B_RENDERER)) &&
@ -1204,42 +1085,51 @@ static HRESULT WINAPI FilterMapper2_EnumMatchingFilters(
return hr;
}
static const IFilterMapper2Vtbl fm2vtbl =
static HRESULT WINAPI FilterMapper3_GetICreateDevEnum(IFilterMapper3 *iface, ICreateDevEnum **ppEnum)
{
TRACE("(%p, %p)\n", iface, ppEnum);
if (!ppEnum)
return E_POINTER;
return CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, &IID_ICreateDevEnum, (void**)ppEnum);
}
static const IFilterMapper3Vtbl fm3vtbl =
{
FilterMapper2_QueryInterface,
FilterMapper2_AddRef,
FilterMapper2_Release,
FilterMapper3_QueryInterface,
FilterMapper3_AddRef,
FilterMapper3_Release,
FilterMapper2_CreateCategory,
FilterMapper2_UnregisterFilter,
FilterMapper2_RegisterFilter,
FilterMapper2_EnumMatchingFilters
FilterMapper3_CreateCategory,
FilterMapper3_UnregisterFilter,
FilterMapper3_RegisterFilter,
FilterMapper3_EnumMatchingFilters,
FilterMapper3_GetICreateDevEnum
};
/*** IUnknown methods ***/
static HRESULT WINAPI FilterMapper_QueryInterface(IFilterMapper * iface, REFIID riid, LPVOID *ppv)
{
FilterMapper2Impl *This = impl_from_IFilterMapper(iface);
FilterMapper3Impl *This = impl_from_IFilterMapper(iface);
TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
return FilterMapper2_QueryInterface((IFilterMapper2*)&This->lpVtbl, riid, ppv);
return FilterMapper3_QueryInterface(&This->IFilterMapper3_iface, riid, ppv);
}
static ULONG WINAPI FilterMapper_AddRef(IFilterMapper * iface)
{
FilterMapper2Impl *This = impl_from_IFilterMapper(iface);
FilterMapper3Impl *This = impl_from_IFilterMapper(iface);
return FilterMapper2_AddRef((IFilterMapper2*)This);
return IUnknown_AddRef(This->outer_unk);
}
static ULONG WINAPI FilterMapper_Release(IFilterMapper * iface)
{
FilterMapper2Impl *This = impl_from_IFilterMapper(iface);
FilterMapper3Impl *This = impl_from_IFilterMapper(iface);
return FilterMapper2_Release((IFilterMapper2*)This);
return IUnknown_Release(This->outer_unk);
}
/*** IFilterMapper methods ***/
@ -1256,7 +1146,7 @@ static HRESULT WINAPI FilterMapper_EnumMatchingFilters(
CLSID clsOutMaj,
CLSID clsOutSub)
{
FilterMapper2Impl *This = impl_from_IFilterMapper(iface);
FilterMapper3Impl *This = impl_from_IFilterMapper(iface);
GUID InputType[2];
GUID OutputType[2];
IEnumMoniker* ppEnumMoniker;
@ -1285,22 +1175,9 @@ static HRESULT WINAPI FilterMapper_EnumMatchingFilters(
*ppEnum = NULL;
hr = IFilterMapper2_EnumMatchingFilters((IFilterMapper2*)This,
&ppEnumMoniker,
0,
TRUE,
dwMerit,
bInputNeeded,
1,
InputType,
NULL,
&GUID_NULL,
bRender,
bOutputNeeded,
1,
OutputType,
NULL,
&GUID_NULL);
hr = IFilterMapper3_EnumMatchingFilters(&This->IFilterMapper3_iface, &ppEnumMoniker, 0, TRUE,
dwMerit, bInputNeeded, 1, InputType, NULL, &GUID_NULL, bRender, bOutputNeeded, 1,
OutputType, NULL, &GUID_NULL);
if (FAILED(hr))
return hr;
@ -1745,23 +1622,23 @@ static const IFilterMapperVtbl fmvtbl =
/*** IUnknown methods ***/
static HRESULT WINAPI AMFilterData_QueryInterface(IAMFilterData * iface, REFIID riid, LPVOID *ppv)
{
FilterMapper2Impl *This = impl_from_IAMFilterData(iface);
FilterMapper3Impl *This = impl_from_IAMFilterData(iface);
return FilterMapper2_QueryInterface((IFilterMapper2*)This, riid, ppv);
return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
}
static ULONG WINAPI AMFilterData_AddRef(IAMFilterData * iface)
{
FilterMapper2Impl *This = impl_from_IAMFilterData(iface);
FilterMapper3Impl *This = impl_from_IAMFilterData(iface);
return FilterMapper2_AddRef((IFilterMapper2*)This);
return IUnknown_AddRef(This->outer_unk);
}
static ULONG WINAPI AMFilterData_Release(IAMFilterData * iface)
{
FilterMapper2Impl *This = impl_from_IAMFilterData(iface);
FilterMapper3Impl *This = impl_from_IAMFilterData(iface);
return FilterMapper2_Release((IFilterMapper2*)This);
return IUnknown_Release(This->outer_unk);
}
/*** IAMFilterData methods ***/
@ -1769,16 +1646,16 @@ static HRESULT WINAPI AMFilterData_ParseFilterData(IAMFilterData* iface,
BYTE *pData, ULONG cb,
BYTE **ppRegFilter2)
{
FilterMapper2Impl *This = impl_from_IAMFilterData(iface);
FilterMapper3Impl *This = impl_from_IAMFilterData(iface);
HRESULT hr = S_OK;
REGFILTER2 *prf2;
static REGFILTER2 *prf2;
TRACE("(%p/%p)->(%p, %d, %p)\n", This, iface, pData, cb, ppRegFilter2);
prf2 = CoTaskMemAlloc(sizeof(*prf2));
if (!prf2)
return E_OUTOFMEMORY;
*ppRegFilter2 = (BYTE *)prf2;
*ppRegFilter2 = (BYTE *)&prf2;
hr = FM2_ReadFilterData(pData, prf2);
if (FAILED(hr))
@ -1795,7 +1672,7 @@ static HRESULT WINAPI AMFilterData_CreateFilterData(IAMFilterData* iface,
BYTE **pRegFilterData,
ULONG *pcb)
{
FilterMapper2Impl *This = impl_from_IAMFilterData(iface);
FilterMapper3Impl *This = impl_from_IAMFilterData(iface);
TRACE("(%p/%p)->(%p, %p, %p)\n", This, iface, prf2, pRegFilterData, pcb);
@ -1809,3 +1686,47 @@ static const IAMFilterDataVtbl AMFilterDataVtbl = {
AMFilterData_ParseFilterData,
AMFilterData_CreateFilterData
};
HRESULT FilterMapper2_create(IUnknown *pUnkOuter, LPVOID *ppObj)
{
FilterMapper3Impl * pFM2impl;
TRACE("(%p, %p)\n", pUnkOuter, ppObj);
pFM2impl = CoTaskMemAlloc(sizeof(*pFM2impl));
if (!pFM2impl)
return E_OUTOFMEMORY;
pFM2impl->IUnknown_inner.lpVtbl = &IInner_VTable;
pFM2impl->IFilterMapper3_iface.lpVtbl = &fm3vtbl;
pFM2impl->IFilterMapper_iface.lpVtbl = &fmvtbl;
pFM2impl->IAMFilterData_iface.lpVtbl = &AMFilterDataVtbl;
pFM2impl->ref = 1;
if (pUnkOuter)
pFM2impl->outer_unk = pUnkOuter;
else
pFM2impl->outer_unk = &pFM2impl->IUnknown_inner;
*ppObj = &pFM2impl->IUnknown_inner;
TRACE("-- created at %p\n", pFM2impl);
return S_OK;
}
HRESULT FilterMapper_create(IUnknown *pUnkOuter, LPVOID *ppObj)
{
FilterMapper3Impl *pFM2impl;
HRESULT hr;
TRACE("(%p, %p)\n", pUnkOuter, ppObj);
hr = FilterMapper2_create(pUnkOuter, (LPVOID*)&pFM2impl);
if (FAILED(hr))
return hr;
*ppObj = &pFM2impl->IFilterMapper_iface;
return hr;
}

View file

@ -2,9 +2,6 @@
*
* Copyright 2002 Lionel Ulmer
*
* This file contains the (internal) driver registration functions,
* driver enumeration APIs and DirectDraw creation functions.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@ -40,16 +37,25 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
return QUARTZ_DllMain( hInstDLL, fdwReason, lpv );
}
static HRESULT SeekingPassThru_create(IUnknown *pUnkOuter, LPVOID *ppObj)
{
return PosPassThru_Construct(pUnkOuter,ppObj); /* from strmbase */
}
/******************************************************************************
* DirectShow ClassFactory
*/
typedef struct {
IClassFactory ITF_IClassFactory;
IClassFactory IClassFactory_iface;
LONG ref;
HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
} IClassFactoryImpl;
static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
{
return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
}
struct object_creation_info
{
const CLSID *clsid;
@ -69,6 +75,7 @@ static const struct object_creation_info object_creation[] =
{ &CLSID_MPEG1Splitter, MPEGSplitter_create },
{ &CLSID_VideoRenderer, VideoRenderer_create },
{ &CLSID_NullRenderer, NullRenderer_create },
{ &CLSID_VideoMixingRenderer9, VMR9Impl_create },
{ &CLSID_VideoRendererDefault, VideoRendererDefault_create },
{ &CLSID_DSoundRender, DSoundRender_create },
{ &CLSID_AudioRender, DSoundRender_create },
@ -78,34 +85,30 @@ static const struct object_creation_info object_creation[] =
{ &CLSID_WAVEParser, WAVEParser_create }
};
static HRESULT WINAPI
DSCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
static HRESULT WINAPI DSCF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj)
{
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
if (IsEqualGUID(riid, &IID_IUnknown)
|| IsEqualGUID(riid, &IID_IClassFactory))
{
IClassFactory_AddRef(iface);
*ppobj = This;
*ppobj = iface;
return S_OK;
}
*ppobj = NULL;
WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
WARN("(%p)->(%s,%p), not found\n", iface, debugstr_guid(riid), ppobj);
return E_NOINTERFACE;
}
static ULONG WINAPI DSCF_AddRef(LPCLASSFACTORY iface)
static ULONG WINAPI DSCF_AddRef(IClassFactory *iface)
{
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
IClassFactoryImpl *This = impl_from_IClassFactory(iface);
return InterlockedIncrement(&This->ref);
}
static ULONG WINAPI DSCF_Release(LPCLASSFACTORY iface)
static ULONG WINAPI DSCF_Release(IClassFactory *iface)
{
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
IClassFactoryImpl *This = impl_from_IClassFactory(iface);
ULONG ref = InterlockedDecrement(&This->ref);
if (ref == 0)
@ -115,16 +118,19 @@ static ULONG WINAPI DSCF_Release(LPCLASSFACTORY iface)
}
static HRESULT WINAPI DSCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter,
REFIID riid, LPVOID *ppobj)
static HRESULT WINAPI DSCF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
REFIID riid, void **ppobj)
{
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
IClassFactoryImpl *This = impl_from_IClassFactory(iface);
HRESULT hres;
LPUNKNOWN punk;
TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
*ppobj = NULL;
if(pOuter && !IsEqualGUID(&IID_IUnknown, riid))
return E_NOINTERFACE;
hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk);
if (SUCCEEDED(hres)) {
hres = IUnknown_QueryInterface(punk, riid, ppobj);
@ -133,9 +139,9 @@ static HRESULT WINAPI DSCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter
return hres;
}
static HRESULT WINAPI DSCF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
static HRESULT WINAPI DSCF_LockServer(IClassFactory *iface, BOOL dolock)
{
IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
IClassFactoryImpl *This = impl_from_IClassFactory(iface);
FIXME("(%p)->(%d),stub!\n",This,dolock);
return S_OK;
}
@ -181,12 +187,12 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
IClassFactoryImpl *factory = CoTaskMemAlloc(sizeof(*factory));
if (factory == NULL) return E_OUTOFMEMORY;
factory->ITF_IClassFactory.lpVtbl = &DSCF_Vtbl;
factory->IClassFactory_iface.lpVtbl = &DSCF_Vtbl;
factory->ref = 1;
factory->pfnCreateInstance = object_creation[i].pfnCreateInstance;
*ppv = &factory->ITF_IClassFactory;
*ppv = &factory->IClassFactory_iface;
return S_OK;
}
}
@ -295,17 +301,15 @@ LONG WINAPI DBToAmpFactor(LONG db)
*/
DWORD WINAPI AMGetErrorTextA(HRESULT hr, LPSTR buffer, DWORD maxlen)
{
unsigned int len;
static const char format[] = "Error: 0x%x";
char error[MAX_ERROR_TEXT_LEN];
DWORD res;
WCHAR errorW[MAX_ERROR_TEXT_LEN];
FIXME("(%x,%p,%d) stub\n", hr, buffer, maxlen);
TRACE("(%x,%p,%d)\n", hr, buffer, maxlen);
if (!buffer)
return 0;
if (!buffer) return 0;
wsprintfA(error, format, hr);
if ((len = strlen(error)) >= maxlen) return 0;
lstrcpyA(buffer, error);
return len;
res = AMGetErrorTextW(hr, errorW, sizeof(errorW)/sizeof(*errorW));
return WideCharToMultiByte(CP_ACP, 0, errorW, res, buffer, maxlen, 0, 0);
}
/***********************************************************************

View file

@ -31,9 +31,20 @@
WINE_DEFAULT_DEBUG_CHANNEL(quartz);
typedef struct StdMediaSample2
{
IMediaSample2 IMediaSample2_iface;
LONG ref;
AM_SAMPLE2_PROPERTIES props;
IMemAllocator * pParent;
struct list listentry;
LONGLONG tMediaStart;
LONGLONG tMediaEnd;
} StdMediaSample2;
typedef struct BaseMemAllocator
{
const IMemAllocatorVtbl * lpVtbl;
IMemAllocator IMemAllocator_iface;
LONG ref;
ALLOCATOR_PROPERTIES props;
@ -52,8 +63,14 @@ typedef struct BaseMemAllocator
CRITICAL_SECTION *pCritSect;
} BaseMemAllocator;
static inline BaseMemAllocator *impl_from_IMemAllocator(IMemAllocator *iface)
{
return CONTAINING_RECORD(iface, BaseMemAllocator, IMemAllocator_iface);
}
static const IMemAllocatorVtbl BaseMemAllocator_VTable;
static const IMediaSample2Vtbl StdMediaSample2_VTable;
static inline StdMediaSample2 *unsafe_impl_from_IMediaSample(IMediaSample * iface);
#define AM_SAMPLE2_PROP_SIZE_WRITABLE FIELD_OFFSET(AM_SAMPLE2_PROPERTIES, pbBuffer)
@ -70,7 +87,7 @@ static HRESULT BaseMemAllocator_Init(HRESULT (* fnAlloc)(IMemAllocator *),
{
assert(fnAlloc && fnFree && fnDestroyed);
pMemAlloc->lpVtbl = &BaseMemAllocator_VTable;
pMemAlloc->IMemAllocator_iface.lpVtbl = &BaseMemAllocator_VTable;
pMemAlloc->ref = 1;
ZeroMemory(&pMemAlloc->props, sizeof(pMemAlloc->props));
@ -93,7 +110,7 @@ static HRESULT BaseMemAllocator_Init(HRESULT (* fnAlloc)(IMemAllocator *),
static HRESULT WINAPI BaseMemAllocator_QueryInterface(IMemAllocator * iface, REFIID riid, LPVOID * ppv)
{
BaseMemAllocator *This = (BaseMemAllocator *)iface;
BaseMemAllocator *This = impl_from_IMemAllocator(iface);
TRACE("(%p)->(%s, %p)\n", This, qzdebugstr_guid(riid), ppv);
*ppv = NULL;
@ -116,7 +133,7 @@ static HRESULT WINAPI BaseMemAllocator_QueryInterface(IMemAllocator * iface, REF
static ULONG WINAPI BaseMemAllocator_AddRef(IMemAllocator * iface)
{
BaseMemAllocator *This = (BaseMemAllocator *)iface;
BaseMemAllocator *This = impl_from_IMemAllocator(iface);
ULONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p)->() AddRef from %d\n", iface, ref - 1);
@ -126,7 +143,7 @@ static ULONG WINAPI BaseMemAllocator_AddRef(IMemAllocator * iface)
static ULONG WINAPI BaseMemAllocator_Release(IMemAllocator * iface)
{
BaseMemAllocator *This = (BaseMemAllocator *)iface;
BaseMemAllocator *This = impl_from_IMemAllocator(iface);
ULONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p)->() Release from %d\n", iface, ref + 1);
@ -145,7 +162,7 @@ static ULONG WINAPI BaseMemAllocator_Release(IMemAllocator * iface)
static HRESULT WINAPI BaseMemAllocator_SetProperties(IMemAllocator * iface, ALLOCATOR_PROPERTIES *pRequest, ALLOCATOR_PROPERTIES *pActual)
{
BaseMemAllocator *This = (BaseMemAllocator *)iface;
BaseMemAllocator *This = impl_from_IMemAllocator(iface);
HRESULT hr;
TRACE("(%p)->(%p, %p)\n", This, pRequest, pActual);
@ -178,7 +195,7 @@ static HRESULT WINAPI BaseMemAllocator_SetProperties(IMemAllocator * iface, ALLO
static HRESULT WINAPI BaseMemAllocator_GetProperties(IMemAllocator * iface, ALLOCATOR_PROPERTIES *pProps)
{
BaseMemAllocator *This = (BaseMemAllocator *)iface;
BaseMemAllocator *This = impl_from_IMemAllocator(iface);
HRESULT hr = S_OK;
TRACE("(%p)->(%p)\n", This, pProps);
@ -194,7 +211,7 @@ static HRESULT WINAPI BaseMemAllocator_GetProperties(IMemAllocator * iface, ALLO
static HRESULT WINAPI BaseMemAllocator_Commit(IMemAllocator * iface)
{
BaseMemAllocator *This = (BaseMemAllocator *)iface;
BaseMemAllocator *This = impl_from_IMemAllocator(iface);
HRESULT hr;
TRACE("(%p)->()\n", This);
@ -238,7 +255,7 @@ static HRESULT WINAPI BaseMemAllocator_Commit(IMemAllocator * iface)
static HRESULT WINAPI BaseMemAllocator_Decommit(IMemAllocator * iface)
{
BaseMemAllocator *This = (BaseMemAllocator *)iface;
BaseMemAllocator *This = impl_from_IMemAllocator(iface);
HRESULT hr;
TRACE("(%p)->()\n", This);
@ -279,7 +296,7 @@ static HRESULT WINAPI BaseMemAllocator_Decommit(IMemAllocator * iface)
static HRESULT WINAPI BaseMemAllocator_GetBuffer(IMemAllocator * iface, IMediaSample ** pSample, REFERENCE_TIME *pStartTime, REFERENCE_TIME *pEndTime, DWORD dwFlags)
{
BaseMemAllocator *This = (BaseMemAllocator *)iface;
BaseMemAllocator *This = impl_from_IMemAllocator(iface);
HRESULT hr = S_OK;
/* NOTE: The pStartTime and pEndTime parameters are not applied to the sample.
@ -319,14 +336,14 @@ static HRESULT WINAPI BaseMemAllocator_GetBuffer(IMemAllocator * iface, IMediaSa
hr = VFW_E_TIMEOUT;
else
{
StdMediaSample2 *ms;
struct list * free = list_head(&This->free_list);
list_remove(free);
list_add_head(&This->used_list, free);
*pSample = (IMediaSample *)LIST_ENTRY(free, StdMediaSample2, listentry);
assert(((StdMediaSample2 *)*pSample)->ref == 0);
ms = LIST_ENTRY(free, StdMediaSample2, listentry);
assert(ms->ref == 0);
*pSample = (IMediaSample *)&ms->IMediaSample2_iface;
IMediaSample_AddRef(*pSample);
}
}
@ -339,10 +356,10 @@ static HRESULT WINAPI BaseMemAllocator_GetBuffer(IMemAllocator * iface, IMediaSa
static HRESULT WINAPI BaseMemAllocator_ReleaseBuffer(IMemAllocator * iface, IMediaSample * pSample)
{
BaseMemAllocator *This = (BaseMemAllocator *)iface;
StdMediaSample2 * pStdSample = (StdMediaSample2 *)pSample;
BaseMemAllocator *This = impl_from_IMemAllocator(iface);
StdMediaSample2 * pStdSample = unsafe_impl_from_IMediaSample(pSample);
HRESULT hr = S_OK;
TRACE("(%p)->(%p)\n", This, pSample);
/* FIXME: make sure that sample is currently on the used list */
@ -408,7 +425,7 @@ static HRESULT StdMediaSample2_Construct(BYTE * pbBuffer, LONG cbBuffer, IMemAll
if (!(*ppSample = CoTaskMemAlloc(sizeof(StdMediaSample2))))
return E_OUTOFMEMORY;
(*ppSample)->lpvtbl = &StdMediaSample2_VTable;
(*ppSample)->IMediaSample2_iface.lpVtbl = &StdMediaSample2_VTable;
(*ppSample)->ref = 0;
ZeroMemory(&(*ppSample)->props, sizeof((*ppSample)->props));
@ -431,47 +448,45 @@ static void StdMediaSample2_Delete(StdMediaSample2 * This)
CoTaskMemFree(This);
}
static HRESULT WINAPI StdMediaSample2_QueryInterface(IMediaSample2 * iface, REFIID riid, LPVOID * ppv)
static inline StdMediaSample2 *impl_from_IMediaSample2(IMediaSample2 * iface)
{
return CONTAINING_RECORD(iface, StdMediaSample2, IMediaSample2_iface);
}
static HRESULT WINAPI StdMediaSample2_QueryInterface(IMediaSample2 * iface, REFIID riid, void ** ppv)
{
StdMediaSample2 *This = (StdMediaSample2 *)iface;
TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv);
*ppv = NULL;
if (IsEqualIID(riid, &IID_IUnknown))
*ppv = This;
else if (IsEqualIID(riid, &IID_IMediaSample))
*ppv = This;
else if (IsEqualIID(riid, &IID_IMediaSample2))
*ppv = This;
if (*ppv)
if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IMediaSample) ||
IsEqualIID(riid, &IID_IMediaSample2))
{
IUnknown_AddRef((IUnknown *)(*ppv));
*ppv = iface;
IMediaSample2_AddRef(iface);
return S_OK;
}
FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
return E_NOINTERFACE;
}
static ULONG WINAPI StdMediaSample2_AddRef(IMediaSample2 * iface)
{
StdMediaSample2 *This = (StdMediaSample2 *)iface;
StdMediaSample2 *This = impl_from_IMediaSample2(iface);
ULONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p)->() AddRef from %d\n", iface, ref - 1);
TRACE("(%p)->(): new ref = %d\n", This, ref);
return ref;
}
static ULONG WINAPI StdMediaSample2_Release(IMediaSample2 * iface)
{
StdMediaSample2 *This = (StdMediaSample2 *)iface;
StdMediaSample2 *This = impl_from_IMediaSample2(iface);
ULONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p)->() Release from %d\n", iface, ref + 1);
TRACE("(%p)->(): new ref = %d\n", This, ref);
if (!ref)
{
@ -479,14 +494,13 @@ static ULONG WINAPI StdMediaSample2_Release(IMediaSample2 * iface)
IMemAllocator_ReleaseBuffer(This->pParent, (IMediaSample *)iface);
else
StdMediaSample2_Delete(This);
return 0;
}
return ref;
}
static HRESULT WINAPI StdMediaSample2_GetPointer(IMediaSample2 * iface, BYTE ** ppBuffer)
{
StdMediaSample2 *This = (StdMediaSample2 *)iface;
StdMediaSample2 *This = impl_from_IMediaSample2(iface);
TRACE("(%p)->(%p)\n", iface, ppBuffer);
@ -503,7 +517,7 @@ static HRESULT WINAPI StdMediaSample2_GetPointer(IMediaSample2 * iface, BYTE **
static LONG WINAPI StdMediaSample2_GetSize(IMediaSample2 * iface)
{
StdMediaSample2 *This = (StdMediaSample2 *)iface;
StdMediaSample2 *This = impl_from_IMediaSample2(iface);
TRACE("StdMediaSample2_GetSize()\n");
@ -512,8 +526,8 @@ static LONG WINAPI StdMediaSample2_GetSize(IMediaSample2 * iface)
static HRESULT WINAPI StdMediaSample2_GetTime(IMediaSample2 * iface, REFERENCE_TIME * pStart, REFERENCE_TIME * pEnd)
{
StdMediaSample2 *This = impl_from_IMediaSample2(iface);
HRESULT hr;
StdMediaSample2 *This = (StdMediaSample2 *)iface;
TRACE("(%p)->(%p, %p)\n", iface, pStart, pEnd);
@ -539,7 +553,7 @@ static HRESULT WINAPI StdMediaSample2_GetTime(IMediaSample2 * iface, REFERENCE_T
static HRESULT WINAPI StdMediaSample2_SetTime(IMediaSample2 * iface, REFERENCE_TIME * pStart, REFERENCE_TIME * pEnd)
{
StdMediaSample2 *This = (StdMediaSample2 *)iface;
StdMediaSample2 *This = impl_from_IMediaSample2(iface);
TRACE("(%p)->(%p, %p)\n", iface, pStart, pEnd);
@ -564,7 +578,7 @@ static HRESULT WINAPI StdMediaSample2_SetTime(IMediaSample2 * iface, REFERENCE_T
static HRESULT WINAPI StdMediaSample2_IsSyncPoint(IMediaSample2 * iface)
{
StdMediaSample2 *This = (StdMediaSample2 *)iface;
StdMediaSample2 *This = impl_from_IMediaSample2(iface);
TRACE("(%p)->()\n", iface);
@ -573,7 +587,7 @@ static HRESULT WINAPI StdMediaSample2_IsSyncPoint(IMediaSample2 * iface)
static HRESULT WINAPI StdMediaSample2_SetSyncPoint(IMediaSample2 * iface, BOOL bIsSyncPoint)
{
StdMediaSample2 *This = (StdMediaSample2 *)iface;
StdMediaSample2 *This = impl_from_IMediaSample2(iface);
TRACE("(%p)->(%s)\n", iface, bIsSyncPoint ? "TRUE" : "FALSE");
@ -587,7 +601,7 @@ static HRESULT WINAPI StdMediaSample2_SetSyncPoint(IMediaSample2 * iface, BOOL b
static HRESULT WINAPI StdMediaSample2_IsPreroll(IMediaSample2 * iface)
{
StdMediaSample2 *This = (StdMediaSample2 *)iface;
StdMediaSample2 *This = impl_from_IMediaSample2(iface);
TRACE("(%p)->()\n", iface);
@ -596,7 +610,7 @@ static HRESULT WINAPI StdMediaSample2_IsPreroll(IMediaSample2 * iface)
static HRESULT WINAPI StdMediaSample2_SetPreroll(IMediaSample2 * iface, BOOL bIsPreroll)
{
StdMediaSample2 *This = (StdMediaSample2 *)iface;
StdMediaSample2 *This = impl_from_IMediaSample2(iface);
TRACE("(%p)->(%s)\n", iface, bIsPreroll ? "TRUE" : "FALSE");
@ -610,7 +624,7 @@ static HRESULT WINAPI StdMediaSample2_SetPreroll(IMediaSample2 * iface, BOOL bIs
static LONG WINAPI StdMediaSample2_GetActualDataLength(IMediaSample2 * iface)
{
StdMediaSample2 *This = (StdMediaSample2 *)iface;
StdMediaSample2 *This = impl_from_IMediaSample2(iface);
TRACE("(%p)->()\n", iface);
@ -619,7 +633,7 @@ static LONG WINAPI StdMediaSample2_GetActualDataLength(IMediaSample2 * iface)
static HRESULT WINAPI StdMediaSample2_SetActualDataLength(IMediaSample2 * iface, LONG len)
{
StdMediaSample2 *This = (StdMediaSample2 *)iface;
StdMediaSample2 *This = impl_from_IMediaSample2(iface);
TRACE("(%p)->(%d)\n", iface, len);
@ -637,7 +651,7 @@ static HRESULT WINAPI StdMediaSample2_SetActualDataLength(IMediaSample2 * iface,
static HRESULT WINAPI StdMediaSample2_GetMediaType(IMediaSample2 * iface, AM_MEDIA_TYPE ** ppMediaType)
{
StdMediaSample2 *This = (StdMediaSample2 *)iface;
StdMediaSample2 *This = impl_from_IMediaSample2(iface);
TRACE("(%p)->(%p)\n", iface, ppMediaType);
@ -656,13 +670,18 @@ static HRESULT WINAPI StdMediaSample2_GetMediaType(IMediaSample2 * iface, AM_MED
static HRESULT WINAPI StdMediaSample2_SetMediaType(IMediaSample2 * iface, AM_MEDIA_TYPE * pMediaType)
{
StdMediaSample2 *This = (StdMediaSample2 *)iface;
StdMediaSample2 *This = impl_from_IMediaSample2(iface);
TRACE("(%p)->(%p)\n", iface, pMediaType);
if (This->props.pMediaType)
{
FreeMediaType(This->props.pMediaType);
else if (!(This->props.pMediaType = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE))))
This->props.pMediaType = NULL;
}
if (!pMediaType)
return S_FALSE;
if (!(This->props.pMediaType = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE))))
return E_OUTOFMEMORY;
return CopyMediaType(This->props.pMediaType, pMediaType);
@ -670,7 +689,7 @@ static HRESULT WINAPI StdMediaSample2_SetMediaType(IMediaSample2 * iface, AM_MED
static HRESULT WINAPI StdMediaSample2_IsDiscontinuity(IMediaSample2 * iface)
{
StdMediaSample2 *This = (StdMediaSample2 *)iface;
StdMediaSample2 *This = impl_from_IMediaSample2(iface);
TRACE("(%p)->()\n", iface);
@ -679,7 +698,7 @@ static HRESULT WINAPI StdMediaSample2_IsDiscontinuity(IMediaSample2 * iface)
static HRESULT WINAPI StdMediaSample2_SetDiscontinuity(IMediaSample2 * iface, BOOL bIsDiscontinuity)
{
StdMediaSample2 *This = (StdMediaSample2 *)iface;
StdMediaSample2 *This = impl_from_IMediaSample2(iface);
TRACE("(%p)->(%s)\n", iface, bIsDiscontinuity ? "TRUE" : "FALSE");
@ -693,7 +712,7 @@ static HRESULT WINAPI StdMediaSample2_SetDiscontinuity(IMediaSample2 * iface, BO
static HRESULT WINAPI StdMediaSample2_GetMediaTime(IMediaSample2 * iface, LONGLONG * pStart, LONGLONG * pEnd)
{
StdMediaSample2 *This = (StdMediaSample2 *)iface;
StdMediaSample2 *This = impl_from_IMediaSample2(iface);
TRACE("(%p)->(%p, %p)\n", iface, pStart, pEnd);
@ -703,12 +722,12 @@ static HRESULT WINAPI StdMediaSample2_GetMediaTime(IMediaSample2 * iface, LONGLO
*pStart = This->tMediaStart;
*pEnd = This->tMediaEnd;
return E_NOTIMPL;
return S_OK;
}
static HRESULT WINAPI StdMediaSample2_SetMediaTime(IMediaSample2 * iface, LONGLONG * pStart, LONGLONG * pEnd)
{
StdMediaSample2 *This = (StdMediaSample2 *)iface;
StdMediaSample2 *This = impl_from_IMediaSample2(iface);
TRACE("(%p)->(%p, %p)\n", iface, pStart, pEnd);
@ -727,7 +746,7 @@ static HRESULT WINAPI StdMediaSample2_SetMediaTime(IMediaSample2 * iface, LONGLO
static HRESULT WINAPI StdMediaSample2_GetProperties(IMediaSample2 * iface, DWORD cbProperties, BYTE * pbProperties)
{
StdMediaSample2 *This = (StdMediaSample2 *)iface;
StdMediaSample2 *This = impl_from_IMediaSample2(iface);
TRACE("(%p)->(%d, %p)\n", iface, cbProperties, pbProperties);
@ -738,7 +757,7 @@ static HRESULT WINAPI StdMediaSample2_GetProperties(IMediaSample2 * iface, DWORD
static HRESULT WINAPI StdMediaSample2_SetProperties(IMediaSample2 * iface, DWORD cbProperties, const BYTE * pbProperties)
{
StdMediaSample2 *This = (StdMediaSample2 *)iface;
StdMediaSample2 *This = impl_from_IMediaSample2(iface);
TRACE("(%p)->(%d, %p)\n", iface, cbProperties, pbProperties);
@ -773,6 +792,16 @@ static const IMediaSample2Vtbl StdMediaSample2_VTable =
StdMediaSample2_SetProperties
};
static inline StdMediaSample2 *unsafe_impl_from_IMediaSample(IMediaSample * iface)
{
IMediaSample2 *iface2 = (IMediaSample2 *)iface;
if (!iface)
return NULL;
assert(iface2->lpVtbl == &StdMediaSample2_VTable);
return impl_from_IMediaSample2(iface2);
}
typedef struct StdMemAllocator
{
BaseMemAllocator base;
@ -780,9 +809,14 @@ typedef struct StdMemAllocator
LPVOID pMemory;
} StdMemAllocator;
static inline StdMemAllocator *StdMemAllocator_from_IMemAllocator(IMemAllocator * iface)
{
return CONTAINING_RECORD(iface, StdMemAllocator, base.IMemAllocator_iface);
}
static HRESULT StdMemAllocator_Alloc(IMemAllocator * iface)
{
StdMemAllocator *This = (StdMemAllocator *)iface;
StdMemAllocator *This = StdMemAllocator_from_IMemAllocator(iface);
StdMediaSample2 * pSample = NULL;
SYSTEM_INFO si;
LONG i;
@ -802,6 +836,9 @@ static HRESULT StdMemAllocator_Alloc(IMemAllocator * iface)
/* allocate memory */
This->pMemory = VirtualAlloc(NULL, (This->base.props.cbBuffer + This->base.props.cbPrefix) * This->base.props.cBuffers, MEM_COMMIT, PAGE_READWRITE);
if (!This->pMemory)
return E_OUTOFMEMORY;
for (i = This->base.props.cBuffers - 1; i >= 0; i--)
{
/* pbBuffer does not start at the base address, it starts at base + cbPrefix */
@ -817,7 +854,7 @@ static HRESULT StdMemAllocator_Alloc(IMemAllocator * iface)
static HRESULT StdMemAllocator_Free(IMemAllocator * iface)
{
StdMemAllocator *This = (StdMemAllocator *)iface;
StdMemAllocator *This = StdMemAllocator_from_IMemAllocator(iface);
struct list * cursor;
if (!list_empty(&This->base.used_list))
@ -850,7 +887,7 @@ static HRESULT StdMemAllocator_Free(IMemAllocator * iface)
static void StdMemAllocator_Destroy(IMemAllocator *iface)
{
StdMemAllocator *This = (StdMemAllocator *)iface;
StdMemAllocator *This = StdMemAllocator_from_IMemAllocator(iface);
This->csState.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&This->csState);

View file

@ -25,7 +25,6 @@
//#include <math.h>
#include "quartz_private.h"
#include "control_private.h"
#include "pin.h"
//#include "uuids.h"
@ -53,30 +52,23 @@ WINE_DEFAULT_DEBUG_CHANNEL(quartz);
#define MPEG_AUDIO_HEADER 1
#define MPEG_NO_HEADER 0
#define SEEK_INTERVAL (ULONGLONG)(10 * 10000000) /* Add an entry every 10 seconds */
struct seek_entry {
ULONGLONG bytepos;
ULONGLONG timepos;
};
typedef struct MPEGSplitterImpl
{
ParserImpl Parser;
LONGLONG EndOfFile;
LONGLONG duration;
LONGLONG position;
DWORD begin_offset;
BYTE header[4];
/* Whether we just seeked (or started playing) */
BOOL seek;
/* Seeking cache */
ULONG seek_entries;
struct seek_entry *seektable;
} MPEGSplitterImpl;
static inline MPEGSplitterImpl *impl_from_IMediaSeeking( IMediaSeeking *iface )
{
return CONTAINING_RECORD(iface, MPEGSplitterImpl, Parser.sourceSeeking.IMediaSeeking_iface);
}
static int MPEGSplitter_head_check(const BYTE *header)
{
/* If this is a possible start code, check for a system or video header */
@ -120,15 +112,14 @@ static const DWORD tabsel_123[2][3][16] = {
static HRESULT parse_header(BYTE *header, LONGLONG *plen, LONGLONG *pduration)
{
int bitrate_index, freq_index, lsf = 1, mpeg1, layer, padding, bitrate, length;
LONGLONG duration;
int bitrate_index, freq_index, lsf = 1, mpeg1, layer, padding, bitrate, length;
if (!(header[0] == 0xff && ((header[1]>>5)&0x7) == 0x7 &&
((header[1]>>1)&0x3) != 0 && ((header[2]>>4)&0xf) != 0xf &&
((header[2]>>2)&0x3) != 0x3))
((header[1]>>1)&0x3) != 0 && ((header[2]>>4)&0xf) != 0xf &&
((header[2]>>2)&0x3) != 0x3))
{
FIXME("Not a valid header: %02x:%02x\n", header[0], header[1]);
FIXME("Not a valid header: %02x:%02x:%02x:%02x\n", header[0], header[1], header[2], header[3]);
return E_INVALIDARG;
}
@ -142,17 +133,23 @@ static HRESULT parse_header(BYTE *header, LONGLONG *plen, LONGLONG *pduration)
padding = ((header[2]>>1)&0x1);
bitrate = tabsel_123[lsf][layer-1][bitrate_index] * 1000;
if (!bitrate || layer != 3)
if (!bitrate)
{
FIXME("Not a valid header: %02x:%02x:%02x:%02x\n", header[0], header[1], header[2], header[3]);
return E_INVALIDARG;
}
if (layer == 3 || layer == 2)
length = 144 * bitrate / freqs[freq_index] + padding;
else
if (layer == 1)
length = 4 * (12 * bitrate / freqs[freq_index] + padding);
else if (layer == 2)
length = 144 * bitrate / freqs[freq_index] + padding;
else if (layer == 3)
length = 144 * bitrate / (freqs[freq_index]<<lsf) + padding;
else
{
ERR("Impossible layer %d\n", layer);
return E_INVALIDARG;
}
duration = (ULONGLONG)10000000 * (ULONGLONG)(length) / (ULONGLONG)(bitrate/8);
*plen = length;
@ -163,10 +160,10 @@ static HRESULT parse_header(BYTE *header, LONGLONG *plen, LONGLONG *pduration)
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);
@ -175,7 +172,8 @@ static HRESULT FillBuffer(MPEGSplitterImpl *This, IMediaSample *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 */
@ -212,9 +210,14 @@ static HRESULT FillBuffer(MPEGSplitterImpl *This, IMediaSample *pCurrentSample)
IMediaSample_SetPreroll(sample, 0);
IMediaSample_SetDiscontinuity(sample, 0);
IMediaSample_SetSyncPoint(sample, 1);
pin->rtCurrent = rtSampleStart;
pin->rtNext = rtSampleStop;
hr = IAsyncReader_Request(pin->pReader, sample, 0);
if (SUCCEEDED(hr))
{
pin->rtCurrent = rtSampleStart;
pin->rtNext = rtSampleStop;
}
else
IMediaSample_Release(sample);
}
if (FAILED(hr))
FIXME("o_Ox%08x\n", hr);
@ -224,9 +227,30 @@ static HRESULT FillBuffer(MPEGSplitterImpl *This, IMediaSample *pCurrentSample)
TRACE("Media time : %u.%03u\n", (DWORD)(This->position/10000000), (DWORD)((This->position/10000)%1000));
IMediaSample_SetTime(pCurrentSample, &time, &This->position);
if (IMediaSample_IsDiscontinuity(pCurrentSample) == S_OK) {
IPin *victim;
EnterCriticalSection(&This->Parser.filter.csFilter);
pOutputPin->pin.pin.tStart = time;
pOutputPin->pin.pin.dRate = This->Parser.sourceSeeking.dRate;
hr = IPin_ConnectedTo(&pOutputPin->pin.pin.IPin_iface, &victim);
if (hr == S_OK)
{
hr = IPin_NewSegment(victim, time, This->Parser.sourceSeeking.llStop,
This->Parser.sourceSeeking.dRate);
if (hr != S_OK)
FIXME("NewSegment returns %08x\n", hr);
IPin_Release(victim);
}
LeaveCriticalSection(&This->Parser.filter.csFilter);
if (hr != S_OK)
return hr;
}
rtstart = (double)(time - pOutputPin->pin.pin.tStart) / pOutputPin->pin.pin.dRate;
rtstop = (double)(This->position - pOutputPin->pin.pin.tStart) / pOutputPin->pin.pin.dRate;
IMediaSample_SetTime(pCurrentSample, &rtstart, &rtstop);
IMediaSample_SetMediaTime(pCurrentSample, &time, &This->position);
hr = OutputPin_SendSample(&pOutputPin->pin, pCurrentSample);
hr = BaseOutputPinImpl_Deliver(&pOutputPin->pin, pCurrentSample);
if (hr != S_OK)
{
@ -280,7 +304,7 @@ static HRESULT MPEGSplitter_process_sample(LPVOID iface, IMediaSample * pSample,
}
}
if (BYTES_FROM_MEDIATIME(tStop) >= This->EndOfFile || This->position >= This->Parser.mediaSeeking.llStop)
if (BYTES_FROM_MEDIATIME(tStop) >= This->EndOfFile || This->position >= This->Parser.sourceSeeking.llStop)
{
unsigned int i;
@ -322,6 +346,7 @@ static HRESULT MPEGSplitter_query_accept(LPVOID iface, const AM_MEDIA_TYPE *pmt)
FIXME("MPEG-1 system streams not yet supported.\n");
else if (IsEqualIID(&pmt->subtype, &MEDIASUBTYPE_MPEG1VideoCD))
FIXME("MPEG-1 VideoCD streams not yet supported.\n");
else FIXME("%s\n", debugstr_guid(&pmt->subtype));
return S_FALSE;
}
@ -449,7 +474,7 @@ static HRESULT MPEGSplitter_init_audio(MPEGSplitterImpl *This, const BYTE *heade
static HRESULT MPEGSplitter_pre_connect(IPin *iface, IPin *pConnectPin, ALLOCATOR_PROPERTIES *props)
{
PullPin *pPin = (PullPin *)iface;
PullPin *pPin = impl_PullPin_from_IPin(iface);
MPEGSplitterImpl *This = (MPEGSplitterImpl*)pPin->pin.pinInfo.pFilter;
HRESULT hr;
LONGLONG pos = 0; /* in bytes */
@ -469,17 +494,23 @@ static HRESULT MPEGSplitter_pre_connect(IPin *iface, IPin *pConnectPin, ALLOCATO
/* Skip ID3 v2 tag, if any */
if (SUCCEEDED(hr) && !memcmp("ID3", header, 3))
do {
UINT length;
UINT length = 0;
hr = IAsyncReader_SyncRead(pPin->pReader, pos, 6, header + 4);
if (FAILED(hr))
break;
pos += 6;
TRACE("Found ID3 v2.%d.%d\n", header[3], header[4]);
length = (header[6] & 0x7F) << 21;
length += (header[7] & 0x7F) << 14;
length += (header[8] & 0x7F) << 7;
length += (header[9] & 0x7F);
TRACE("Length: %u\n", length);
if(header[3] <= 4 && header[4] != 0xff &&
(header[5]&0x0f) == 0 && (header[6]&0x80) == 0 &&
(header[7]&0x80) == 0 && (header[8]&0x80) == 0 &&
(header[9]&0x80) == 0)
{
length = (header[6]<<21) | (header[7]<<14) |
(header[8]<< 7) | (header[9] );
if((header[5]&0x10))
length += 10;
TRACE("Length: %u\n", length);
}
pos += length;
/* Read the real header for the mpeg splitter */
@ -502,22 +533,17 @@ static HRESULT MPEGSplitter_pre_connect(IPin *iface, IPin *pConnectPin, ALLOCATO
This->begin_offset = pos;
memcpy(This->header, header, 4);
This->seektable[0].bytepos = pos;
This->seektable[0].timepos = 0;
switch(streamtype)
{
case MPEG_AUDIO_HEADER:
{
LONGLONG duration = 0;
DWORD last_entry = 0;
DWORD ticks = GetTickCount();
WAVEFORMATEX *format;
hr = MPEGSplitter_init_audio(This, header, &piOutput, &amt);
if (SUCCEEDED(hr))
{
WAVEFORMATEX *format = (WAVEFORMATEX*)amt.pbFormat;
format = (WAVEFORMATEX*)amt.pbFormat;
props->cbAlign = 1;
props->cbPrefix = 0;
@ -537,59 +563,20 @@ static HRESULT MPEGSplitter_pre_connect(IPin *iface, IPin *pConnectPin, ALLOCATO
}
/* Check for idv1 tag, and remove it from stream if found */
hr = IAsyncReader_SyncRead(pPin->pReader, This->EndOfFile-128, 3, header+4);
hr = IAsyncReader_SyncRead(pPin->pReader, This->EndOfFile-128, 3, header);
if (FAILED(hr))
break;
if (!strncmp((char*)header+4, "TAG", 3))
if (!strncmp((char*)header, "TAG", 3))
This->EndOfFile -= 128;
This->Parser.pInputPin->rtStop = MEDIATIME_FROM_BYTES(This->EndOfFile);
This->Parser.pInputPin->rtStart = This->Parser.pInputPin->rtCurrent = MEDIATIME_FROM_BYTES(This->begin_offset);
/* http://mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm has a whole read up on audio headers */
while (pos + 3 < This->EndOfFile)
{
LONGLONG length = 0;
hr = IAsyncReader_SyncRead(pPin->pReader, pos, 4, header);
if (hr != S_OK)
break;
while (parse_header(header, &length, &duration))
{
/* No valid header yet; shift by a byte and check again */
memmove(header, header+1, 3);
hr = IAsyncReader_SyncRead(pPin->pReader, pos++, 1, header + 3);
if (hr != S_OK || This->EndOfFile - pos < 4)
break;
}
pos += length;
if (This->seektable && (duration / SEEK_INTERVAL) > last_entry)
{
if (last_entry + 1 > duration / SEEK_INTERVAL)
{
ERR("Somehow skipped %d interval lengths instead of 1\n", (DWORD)(duration/SEEK_INTERVAL) - (last_entry + 1));
}
++last_entry;
TRACE("Entry: %u\n", last_entry);
if (last_entry >= This->seek_entries)
{
This->seek_entries += 64;
This->seektable = CoTaskMemRealloc(This->seektable, (This->seek_entries)*sizeof(struct seek_entry));
}
This->seektable[last_entry].bytepos = pos;
This->seektable[last_entry].timepos = duration;
}
TRACE("Pos: %x%08x/%x%08x\n", (DWORD)(pos >> 32), (DWORD)pos, (DWORD)(This->EndOfFile>>32), (DWORD)This->EndOfFile);
}
hr = S_OK;
duration = (This->EndOfFile-This->begin_offset) * 10000000 / format->nAvgBytesPerSec;
TRACE("Duration: %d seconds\n", (DWORD)(duration / 10000000));
TRACE("Parsing took %u ms\n", GetTickCount() - ticks);
This->duration = duration;
This->Parser.mediaSeeking.llCurrent = 0;
This->Parser.mediaSeeking.llDuration = duration;
This->Parser.mediaSeeking.llStop = duration;
This->Parser.sourceSeeking.llCurrent = 0;
This->Parser.sourceSeeking.llDuration = duration;
This->Parser.sourceSeeking.llStop = duration;
break;
}
case MPEG_VIDEO_HEADER:
@ -618,80 +605,67 @@ static HRESULT MPEGSplitter_cleanup(LPVOID iface)
return S_OK;
}
static HRESULT MPEGSplitter_seek(IBaseFilter *iface)
static HRESULT WINAPI MPEGSplitter_seek(IMediaSeeking *iface)
{
MPEGSplitterImpl *This = (MPEGSplitterImpl*)iface;
MPEGSplitterImpl *This = impl_from_IMediaSeeking(iface);
PullPin *pPin = This->Parser.pInputPin;
LONGLONG newpos, timepos, bytepos;
HRESULT hr = S_OK;
HRESULT hr = E_INVALIDARG;
BYTE header[4];
newpos = This->Parser.mediaSeeking.llCurrent;
if (newpos > This->duration)
{
WARN("Requesting position %x%08x beyond end of stream %x%08x\n", (DWORD)(newpos>>32), (DWORD)newpos, (DWORD)(This->duration>>32), (DWORD)This->duration);
return E_INVALIDARG;
}
newpos = This->Parser.sourceSeeking.llCurrent;
if (This->position/1000000 == newpos/1000000)
{
TRACE("Requesting position %x%08x same as current position %x%08x\n", (DWORD)(newpos>>32), (DWORD)newpos, (DWORD)(This->position>>32), (DWORD)This->position);
return S_OK;
}
/* Position, cached */
bytepos = This->seektable[newpos / SEEK_INTERVAL].bytepos;
timepos = This->seektable[newpos / SEEK_INTERVAL].timepos;
hr = IAsyncReader_SyncRead(pPin->pReader, bytepos, 4, header);
bytepos = This->begin_offset;
timepos = 0;
/* http://mpgedit.org/mpgedit/mpeg_format/mpeghdr.htm has a whole read up on audio headers */
while (bytepos + 3 < This->EndOfFile)
{
LONGLONG duration = timepos;
LONGLONG length = 0;
hr = IAsyncReader_SyncRead(pPin->pReader, bytepos, 4, header);
if (hr != S_OK || timepos >= newpos)
if (hr != S_OK)
break;
while (parse_header(header, &length, &timepos) && bytepos + 3 < This->EndOfFile)
while ((hr=parse_header(header, &length, &duration)) != S_OK &&
bytepos + 4 < This->EndOfFile)
{
/* No valid header yet; shift by a byte and check again */
memmove(header, header+1, 3);
hr = IAsyncReader_SyncRead(pPin->pReader, ++bytepos, 1, header + 3);
hr = IAsyncReader_SyncRead(pPin->pReader, ++bytepos + 3, 1, header + 3);
if (hr != S_OK)
break;
}
bytepos += length;
TRACE("Pos: %x%08x/%x%08x\n", (DWORD)(bytepos >> 32), (DWORD)bytepos, (DWORD)(This->EndOfFile>>32), (DWORD)This->EndOfFile);
}
if (hr != S_OK || duration > newpos)
break;
bytepos += length;
timepos = duration;
}
if (SUCCEEDED(hr))
{
PullPin *pin = This->Parser.pInputPin;
IPin *victim = NULL;
TRACE("Moving sound to %08u bytes!\n", (DWORD)bytepos);
EnterCriticalSection(&pin->thread_lock);
IPin_BeginFlush((IPin *)pin);
IPin_BeginFlush(&pin->pin.IPin_iface);
/* Make sure this is done while stopped, BeginFlush takes care of this */
EnterCriticalSection(&This->Parser.csFilter);
EnterCriticalSection(&This->Parser.filter.csFilter);
memcpy(This->header, header, 4);
IPin_ConnectedTo(This->Parser.ppPins[1], &victim);
if (victim)
{
IPin_NewSegment(victim, newpos, This->duration, pin->dRate);
IPin_Release(victim);
}
pin->rtStart = pin->rtCurrent = MEDIATIME_FROM_BYTES(bytepos);
pin->rtStop = MEDIATIME_FROM_BYTES((REFERENCE_TIME)This->EndOfFile);
This->seek = TRUE;
This->position = newpos;
LeaveCriticalSection(&This->Parser.csFilter);
LeaveCriticalSection(&This->Parser.filter.csFilter);
TRACE("Done flushing\n");
IPin_EndFlush((IPin *)pin);
IPin_EndFlush(&pin->pin.IPin_iface);
LeaveCriticalSection(&pin->thread_lock);
}
return hr;
@ -712,7 +686,9 @@ static HRESULT MPEGSplitter_first_request(LPVOID iface)
IMediaSample *sample;
TRACE("Seeking? %d\n", This->seek);
assert(parse_header(This->header, &length, NULL) == S_OK);
hr = parse_header(This->header, &length, NULL);
assert(hr == S_OK);
if (pin->rtCurrent >= pin->rtStop)
{
@ -735,15 +711,19 @@ static HRESULT MPEGSplitter_first_request(LPVOID iface)
hr = IMediaSample_SetTime(sample, &rtSampleStart, &rtSampleStop);
pin->rtCurrent = pin->rtNext;
pin->rtNext = rtSampleStop;
IMediaSample_SetPreroll(sample, FALSE);
IMediaSample_SetDiscontinuity(sample, This->seek);
IMediaSample_SetDiscontinuity(sample, TRUE);
IMediaSample_SetSyncPoint(sample, 1);
This->seek = 0;
hr = IAsyncReader_Request(pin->pReader, sample, 0);
if (SUCCEEDED(hr))
{
pin->rtCurrent = pin->rtNext;
pin->rtNext = rtSampleStop;
}
else
IMediaSample_Release(sample);
}
if (FAILED(hr))
ERR("Horsemen of the apocalypse came to bring error 0x%08x\n", hr);
@ -787,14 +767,6 @@ HRESULT MPEGSplitter_create(IUnknown * pUnkOuter, LPVOID * ppv)
return E_OUTOFMEMORY;
ZeroMemory(This, sizeof(MPEGSplitterImpl));
This->seektable = CoTaskMemAlloc(sizeof(struct seek_entry) * 64);
if (!This->seektable)
{
CoTaskMemFree(This);
return E_OUTOFMEMORY;
}
This->seek_entries = 64;
hr = Parser_Create(&(This->Parser), &MPEGSplitter_Vtbl, &CLSID_MPEG1Splitter, MPEGSplitter_process_sample, MPEGSplitter_query_accept, MPEGSplitter_pre_connect, MPEGSplitter_cleanup, MPEGSplitter_disconnect, MPEGSplitter_first_request, NULL, NULL, MPEGSplitter_seek, NULL);
if (FAILED(hr))
{

View file

@ -24,7 +24,6 @@
#define NONAMELESSSTRUCT
#define NONAMELESSUNION
#include "quartz_private.h"
#include "control_private.h"
#include "pin.h"
//#include "uuids.h"
@ -42,181 +41,75 @@
WINE_DEFAULT_DEBUG_CHANNEL(quartz);
static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0};
static const WCHAR wcsAltInputPinName[] = {'I','n',0};
static const IBaseFilterVtbl NullRenderer_Vtbl;
static const IUnknownVtbl IInner_VTable;
static const IPinVtbl NullRenderer_InputPin_Vtbl;
typedef struct NullRendererImpl
{
const IBaseFilterVtbl * lpVtbl;
const IUnknownVtbl * IInner_vtbl;
LONG refCount;
CRITICAL_SECTION csFilter;
FILTER_STATE state;
REFERENCE_TIME rtStreamStart;
IReferenceClock * pClock;
FILTER_INFO filterInfo;
InputPin *pInputPin;
IUnknown * pUnkOuter;
BOOL bUnkOuterValid;
BOOL bAggregatable;
MediaSeekingImpl mediaSeeking;
BaseRenderer renderer;
IUnknown IUnknown_inner;
IAMFilterMiscFlags IAMFilterMiscFlags_iface;
IUnknown *outer_unk;
} NullRendererImpl;
static HRESULT NullRenderer_Sample(LPVOID iface, IMediaSample * pSample)
static HRESULT WINAPI NullRenderer_DoRenderSample(BaseRenderer *iface, IMediaSample *pMediaSample)
{
NullRendererImpl *This = iface;
HRESULT hr = S_OK;
TRACE("%p %p\n", iface, pSample);
EnterCriticalSection(&This->csFilter);
if (This->pInputPin->flushing || This->pInputPin->end_of_stream)
hr = S_FALSE;
LeaveCriticalSection(&This->csFilter);
return hr;
return S_OK;
}
static HRESULT NullRenderer_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt)
static HRESULT WINAPI NullRenderer_CheckMediaType(BaseRenderer *iface, const AM_MEDIA_TYPE * pmt)
{
TRACE("Not a stub!\n");
return S_OK;
}
static inline NullRendererImpl *impl_from_IMediaSeeking( IMediaSeeking *iface )
{
return (NullRendererImpl *)((char*)iface - FIELD_OFFSET(NullRendererImpl, mediaSeeking.lpVtbl));
}
static HRESULT WINAPI NullRendererImpl_Seeking_QueryInterface(IMediaSeeking * iface, REFIID riid, LPVOID * ppv)
{
NullRendererImpl *This = impl_from_IMediaSeeking(iface);
return IUnknown_QueryInterface((IUnknown *)This, riid, ppv);
}
static ULONG WINAPI NullRendererImpl_Seeking_AddRef(IMediaSeeking * iface)
{
NullRendererImpl *This = impl_from_IMediaSeeking(iface);
return IUnknown_AddRef((IUnknown *)This);
}
static ULONG WINAPI NullRendererImpl_Seeking_Release(IMediaSeeking * iface)
{
NullRendererImpl *This = impl_from_IMediaSeeking(iface);
return IUnknown_Release((IUnknown *)This);
}
static const IMediaSeekingVtbl TransformFilter_Seeking_Vtbl =
{
NullRendererImpl_Seeking_QueryInterface,
NullRendererImpl_Seeking_AddRef,
NullRendererImpl_Seeking_Release,
MediaSeekingImpl_GetCapabilities,
MediaSeekingImpl_CheckCapabilities,
MediaSeekingImpl_IsFormatSupported,
MediaSeekingImpl_QueryPreferredFormat,
MediaSeekingImpl_GetTimeFormat,
MediaSeekingImpl_IsUsingTimeFormat,
MediaSeekingImpl_SetTimeFormat,
MediaSeekingImpl_GetDuration,
MediaSeekingImpl_GetStopPosition,
MediaSeekingImpl_GetCurrentPosition,
MediaSeekingImpl_ConvertTimeFormat,
MediaSeekingImpl_SetPositions,
MediaSeekingImpl_GetPositions,
MediaSeekingImpl_GetAvailable,
MediaSeekingImpl_SetRate,
MediaSeekingImpl_GetRate,
MediaSeekingImpl_GetPreroll
static const BaseRendererFuncTable RendererFuncTable = {
NullRenderer_CheckMediaType,
NullRenderer_DoRenderSample,
/**/
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
/**/
NULL,
NULL,
NULL,
NULL,
NULL,
};
static HRESULT NullRendererImpl_Change(IBaseFilter *iface)
static inline NullRendererImpl *impl_from_IUnknown(IUnknown *iface)
{
TRACE("(%p)\n", iface);
return S_OK;
return CONTAINING_RECORD(iface, NullRendererImpl, IUnknown_inner);
}
HRESULT NullRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv)
static HRESULT WINAPI NullRendererInner_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
{
HRESULT hr;
PIN_INFO piInput;
NullRendererImpl * pNullRenderer;
NullRendererImpl *This = impl_from_IUnknown(iface);
TRACE("(%p, %p)\n", pUnkOuter, ppv);
*ppv = NULL;
pNullRenderer = CoTaskMemAlloc(sizeof(NullRendererImpl));
pNullRenderer->pUnkOuter = pUnkOuter;
pNullRenderer->bUnkOuterValid = FALSE;
pNullRenderer->bAggregatable = FALSE;
pNullRenderer->IInner_vtbl = &IInner_VTable;
pNullRenderer->lpVtbl = &NullRenderer_Vtbl;
pNullRenderer->refCount = 1;
InitializeCriticalSection(&pNullRenderer->csFilter);
pNullRenderer->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": NullRendererImpl.csFilter");
pNullRenderer->state = State_Stopped;
pNullRenderer->pClock = NULL;
ZeroMemory(&pNullRenderer->filterInfo, sizeof(FILTER_INFO));
/* construct input pin */
piInput.dir = PINDIR_INPUT;
piInput.pFilter = (IBaseFilter *)pNullRenderer;
lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
hr = InputPin_Construct(&NullRenderer_InputPin_Vtbl, &piInput, NullRenderer_Sample, (LPVOID)pNullRenderer, NullRenderer_QueryAccept, NULL, &pNullRenderer->csFilter, NULL, (IPin **)&pNullRenderer->pInputPin);
if (SUCCEEDED(hr))
{
MediaSeekingImpl_Init((IBaseFilter*)pNullRenderer, NullRendererImpl_Change, NullRendererImpl_Change, NullRendererImpl_Change, &pNullRenderer->mediaSeeking, &pNullRenderer->csFilter);
pNullRenderer->mediaSeeking.lpVtbl = &TransformFilter_Seeking_Vtbl;
*ppv = pNullRenderer;
}
else
{
pNullRenderer->csFilter.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&pNullRenderer->csFilter);
CoTaskMemFree(pNullRenderer);
}
return hr;
}
static HRESULT WINAPI NullRendererInner_QueryInterface(IUnknown * iface, REFIID riid, LPVOID * ppv)
{
ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface);
TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
if (This->bAggregatable)
This->bUnkOuterValid = TRUE;
*ppv = NULL;
if (IsEqualIID(riid, &IID_IUnknown))
*ppv = &This->IInner_vtbl;
else if (IsEqualIID(riid, &IID_IPersist))
*ppv = This;
else if (IsEqualIID(riid, &IID_IMediaFilter))
*ppv = This;
else if (IsEqualIID(riid, &IID_IBaseFilter))
*ppv = This;
else if (IsEqualIID(riid, &IID_IMediaSeeking))
*ppv = &This->mediaSeeking;
*ppv = &This->IUnknown_inner;
else if (IsEqualIID(riid, &IID_IAMFilterMiscFlags))
*ppv = &This->IAMFilterMiscFlags_iface;
else
{
HRESULT hr;
hr = BaseRendererImpl_QueryInterface(&This->renderer.filter.IBaseFilter_iface, riid, ppv);
if (SUCCEEDED(hr))
return hr;
}
if (*ppv)
{
IUnknown_AddRef((IUnknown *)(*ppv));
IUnknown_AddRef((IUnknown *)*ppv);
return S_OK;
}
@ -226,49 +119,24 @@ static HRESULT WINAPI NullRendererInner_QueryInterface(IUnknown * iface, REFIID
return E_NOINTERFACE;
}
static ULONG WINAPI NullRendererInner_AddRef(IUnknown * iface)
static ULONG WINAPI NullRendererInner_AddRef(IUnknown *iface)
{
ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface);
ULONG refCount = InterlockedIncrement(&This->refCount);
TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1);
return refCount;
NullRendererImpl *This = impl_from_IUnknown(iface);
return BaseFilterImpl_AddRef(&This->renderer.filter.IBaseFilter_iface);
}
static ULONG WINAPI NullRendererInner_Release(IUnknown * iface)
static ULONG WINAPI NullRendererInner_Release(IUnknown *iface)
{
ICOM_THIS_MULTI(NullRendererImpl, IInner_vtbl, iface);
ULONG refCount = InterlockedDecrement(&This->refCount);
TRACE("(%p/%p)->() Release from %d\n", This, iface, refCount + 1);
NullRendererImpl *This = impl_from_IUnknown(iface);
ULONG refCount = BaseFilterImpl_Release(&This->renderer.filter.IBaseFilter_iface);
if (!refCount)
{
IPin *pConnectedTo;
if (This->pClock)
IReferenceClock_Release(This->pClock);
if (SUCCEEDED(IPin_ConnectedTo((IPin *)This->pInputPin, &pConnectedTo)))
{
IPin_Disconnect(pConnectedTo);
IPin_Release(pConnectedTo);
}
IPin_Disconnect((IPin *)This->pInputPin);
IPin_Release((IPin *)This->pInputPin);
This->lpVtbl = NULL;
This->csFilter.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&This->csFilter);
TRACE("Destroying Null Renderer\n");
CoTaskMemFree(This);
return 0;
}
else
return refCount;
return refCount;
}
static const IUnknownVtbl IInner_VTable =
@ -278,253 +146,27 @@ static const IUnknownVtbl IInner_VTable =
NullRendererInner_Release
};
static inline NullRendererImpl *impl_from_IBaseFilter(IBaseFilter *iface)
{
return CONTAINING_RECORD(iface, NullRendererImpl, renderer.filter.IBaseFilter_iface);
}
static HRESULT WINAPI NullRenderer_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
{
NullRendererImpl *This = (NullRendererImpl *)iface;
if (This->bAggregatable)
This->bUnkOuterValid = TRUE;
if (This->pUnkOuter)
{
if (This->bAggregatable)
return IUnknown_QueryInterface(This->pUnkOuter, riid, ppv);
if (IsEqualIID(riid, &IID_IUnknown))
{
HRESULT hr;
IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
hr = IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
This->bAggregatable = TRUE;
return hr;
}
*ppv = NULL;
return E_NOINTERFACE;
}
return IUnknown_QueryInterface((IUnknown *)&(This->IInner_vtbl), riid, ppv);
NullRendererImpl *This = impl_from_IBaseFilter(iface);
return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
}
static ULONG WINAPI NullRenderer_AddRef(IBaseFilter * iface)
{
NullRendererImpl *This = (NullRendererImpl *)iface;
if (This->pUnkOuter && This->bUnkOuterValid)
return IUnknown_AddRef(This->pUnkOuter);
return IUnknown_AddRef((IUnknown *)&(This->IInner_vtbl));
NullRendererImpl *This = impl_from_IBaseFilter(iface);
return IUnknown_AddRef(This->outer_unk);
}
static ULONG WINAPI NullRenderer_Release(IBaseFilter * iface)
{
NullRendererImpl *This = (NullRendererImpl *)iface;
if (This->pUnkOuter && This->bUnkOuterValid)
return IUnknown_Release(This->pUnkOuter);
return IUnknown_Release((IUnknown *)&(This->IInner_vtbl));
}
/** IPersist methods **/
static HRESULT WINAPI NullRenderer_GetClassID(IBaseFilter * iface, CLSID * pClsid)
{
NullRendererImpl *This = (NullRendererImpl *)iface;
TRACE("(%p/%p)->(%p)\n", This, iface, pClsid);
*pClsid = CLSID_NullRenderer;
return S_OK;
}
/** IMediaFilter methods **/
static HRESULT WINAPI NullRenderer_Stop(IBaseFilter * iface)
{
NullRendererImpl *This = (NullRendererImpl *)iface;
TRACE("(%p/%p)->()\n", This, iface);
EnterCriticalSection(&This->csFilter);
{
This->state = State_Stopped;
}
LeaveCriticalSection(&This->csFilter);
return S_OK;
}
static HRESULT WINAPI NullRenderer_Pause(IBaseFilter * iface)
{
NullRendererImpl *This = (NullRendererImpl *)iface;
TRACE("(%p/%p)->()\n", This, iface);
EnterCriticalSection(&This->csFilter);
{
if (This->state == State_Stopped)
This->pInputPin->end_of_stream = 0;
This->state = State_Paused;
}
LeaveCriticalSection(&This->csFilter);
return S_OK;
}
static HRESULT WINAPI NullRenderer_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
{
NullRendererImpl *This = (NullRendererImpl *)iface;
TRACE("(%p/%p)->(%s)\n", This, iface, wine_dbgstr_longlong(tStart));
EnterCriticalSection(&This->csFilter);
{
This->rtStreamStart = tStart;
This->state = State_Running;
This->pInputPin->end_of_stream = 0;
}
LeaveCriticalSection(&This->csFilter);
return S_OK;
}
static HRESULT WINAPI NullRenderer_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
{
NullRendererImpl *This = (NullRendererImpl *)iface;
TRACE("(%p/%p)->(%d, %p)\n", This, iface, dwMilliSecsTimeout, pState);
EnterCriticalSection(&This->csFilter);
{
*pState = This->state;
}
LeaveCriticalSection(&This->csFilter);
return S_OK;
}
static HRESULT WINAPI NullRenderer_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
{
NullRendererImpl *This = (NullRendererImpl *)iface;
TRACE("(%p/%p)->(%p)\n", This, iface, pClock);
EnterCriticalSection(&This->csFilter);
{
if (This->pClock)
IReferenceClock_Release(This->pClock);
This->pClock = pClock;
if (This->pClock)
IReferenceClock_AddRef(This->pClock);
}
LeaveCriticalSection(&This->csFilter);
return S_OK;
}
static HRESULT WINAPI NullRenderer_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
{
NullRendererImpl *This = (NullRendererImpl *)iface;
TRACE("(%p/%p)->(%p)\n", This, iface, ppClock);
EnterCriticalSection(&This->csFilter);
{
*ppClock = This->pClock;
if (This->pClock)
IReferenceClock_AddRef(This->pClock);
}
LeaveCriticalSection(&This->csFilter);
return S_OK;
}
/** IBaseFilter implementation **/
static HRESULT NullRenderer_GetPin(IBaseFilter *iface, ULONG pos, IPin **pin, DWORD *lastsynctick)
{
NullRendererImpl *This = (NullRendererImpl *)iface;
/* Our pins are static, not changing so setting static tick count is ok */
*lastsynctick = 0;
if (pos >= 1)
return S_FALSE;
*pin = (IPin *)This->pInputPin;
IPin_AddRef(*pin);
return S_OK;
}
static HRESULT WINAPI NullRenderer_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
{
NullRendererImpl *This = (NullRendererImpl *)iface;
TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
return IEnumPinsImpl_Construct(ppEnum, NullRenderer_GetPin, iface);
}
static HRESULT WINAPI NullRenderer_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
{
NullRendererImpl *This = (NullRendererImpl *)iface;
TRACE("(%p/%p)->(%p,%p)\n", This, iface, debugstr_w(Id), ppPin);
if (!Id || !ppPin)
return E_POINTER;
if (!lstrcmpiW(Id,wcsInputPinName) || !lstrcmpiW(Id,wcsAltInputPinName))
{
*ppPin = (IPin *)This->pInputPin;
IPin_AddRef(*ppPin);
return S_OK;
}
*ppPin = NULL;
return VFW_E_NOT_FOUND;
}
static HRESULT WINAPI NullRenderer_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
{
NullRendererImpl *This = (NullRendererImpl *)iface;
TRACE("(%p/%p)->(%p)\n", This, iface, pInfo);
strcpyW(pInfo->achName, This->filterInfo.achName);
pInfo->pGraph = This->filterInfo.pGraph;
if (pInfo->pGraph)
IFilterGraph_AddRef(pInfo->pGraph);
return S_OK;
}
static HRESULT WINAPI NullRenderer_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName)
{
NullRendererImpl *This = (NullRendererImpl *)iface;
TRACE("(%p/%p)->(%p, %s)\n", This, iface, pGraph, debugstr_w(pName));
EnterCriticalSection(&This->csFilter);
{
if (pName)
strcpyW(This->filterInfo.achName, pName);
else
*This->filterInfo.achName = '\0';
This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
}
LeaveCriticalSection(&This->csFilter);
return S_OK;
}
static HRESULT WINAPI NullRenderer_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo)
{
NullRendererImpl *This = (NullRendererImpl *)iface;
TRACE("(%p/%p)->(%p)\n", This, iface, pVendorInfo);
return E_NOTIMPL;
NullRendererImpl *This = impl_from_IBaseFilter(iface);
return IUnknown_Release(This->outer_unk);
}
static const IBaseFilterVtbl NullRenderer_Vtbl =
@ -532,62 +174,85 @@ static const IBaseFilterVtbl NullRenderer_Vtbl =
NullRenderer_QueryInterface,
NullRenderer_AddRef,
NullRenderer_Release,
NullRenderer_GetClassID,
NullRenderer_Stop,
NullRenderer_Pause,
NullRenderer_Run,
NullRenderer_GetState,
NullRenderer_SetSyncSource,
NullRenderer_GetSyncSource,
NullRenderer_EnumPins,
NullRenderer_FindPin,
NullRenderer_QueryFilterInfo,
NullRenderer_JoinFilterGraph,
NullRenderer_QueryVendorInfo
BaseFilterImpl_GetClassID,
BaseRendererImpl_Stop,
BaseRendererImpl_Pause,
BaseRendererImpl_Run,
BaseRendererImpl_GetState,
BaseRendererImpl_SetSyncSource,
BaseFilterImpl_GetSyncSource,
BaseFilterImpl_EnumPins,
BaseRendererImpl_FindPin,
BaseFilterImpl_QueryFilterInfo,
BaseFilterImpl_JoinFilterGraph,
BaseFilterImpl_QueryVendorInfo
};
static HRESULT WINAPI NullRenderer_InputPin_EndOfStream(IPin * iface)
static NullRendererImpl *impl_from_IAMFilterMiscFlags(IAMFilterMiscFlags *iface)
{
InputPin* This = (InputPin*)iface;
IMediaEventSink* pEventSink;
IFilterGraph *graph;
HRESULT hr = S_OK;
TRACE("(%p/%p)->()\n", This, iface);
InputPin_EndOfStream(iface);
graph = ((NullRendererImpl*)This->pin.pinInfo.pFilter)->filterInfo.pGraph;
if (graph)
{
hr = IFilterGraph_QueryInterface(((NullRendererImpl*)This->pin.pinInfo.pFilter)->filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink);
if (SUCCEEDED(hr))
{
hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, 0);
IMediaEventSink_Release(pEventSink);
}
}
return hr;
return CONTAINING_RECORD(iface, NullRendererImpl, IAMFilterMiscFlags_iface);
}
static const IPinVtbl NullRenderer_InputPin_Vtbl =
static HRESULT WINAPI AMFilterMiscFlags_QueryInterface(IAMFilterMiscFlags *iface, REFIID riid,
void **ppv)
{
InputPin_QueryInterface,
IPinImpl_AddRef,
InputPin_Release,
InputPin_Connect,
InputPin_ReceiveConnection,
IPinImpl_Disconnect,
IPinImpl_ConnectedTo,
IPinImpl_ConnectionMediaType,
IPinImpl_QueryPinInfo,
IPinImpl_QueryDirection,
IPinImpl_QueryId,
IPinImpl_QueryAccept,
IPinImpl_EnumMediaTypes,
IPinImpl_QueryInternalConnections,
NullRenderer_InputPin_EndOfStream,
InputPin_BeginFlush,
InputPin_EndFlush,
InputPin_NewSegment
NullRendererImpl *This = impl_from_IAMFilterMiscFlags(iface);
return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
}
static ULONG WINAPI AMFilterMiscFlags_AddRef(IAMFilterMiscFlags *iface)
{
NullRendererImpl *This = impl_from_IAMFilterMiscFlags(iface);
return IUnknown_AddRef(This->outer_unk);
}
static ULONG WINAPI AMFilterMiscFlags_Release(IAMFilterMiscFlags *iface)
{
NullRendererImpl *This = impl_from_IAMFilterMiscFlags(iface);
return IUnknown_Release(This->outer_unk);
}
static ULONG WINAPI AMFilterMiscFlags_GetMiscFlags(IAMFilterMiscFlags *iface)
{
return AM_FILTER_MISC_FLAGS_IS_RENDERER;
}
static const IAMFilterMiscFlagsVtbl IAMFilterMiscFlags_Vtbl = {
AMFilterMiscFlags_QueryInterface,
AMFilterMiscFlags_AddRef,
AMFilterMiscFlags_Release,
AMFilterMiscFlags_GetMiscFlags
};
HRESULT NullRenderer_create(IUnknown *pUnkOuter, void **ppv)
{
HRESULT hr;
NullRendererImpl *pNullRenderer;
TRACE("(%p, %p)\n", pUnkOuter, ppv);
*ppv = NULL;
pNullRenderer = CoTaskMemAlloc(sizeof(NullRendererImpl));
pNullRenderer->IUnknown_inner.lpVtbl = &IInner_VTable;
pNullRenderer->IAMFilterMiscFlags_iface.lpVtbl = &IAMFilterMiscFlags_Vtbl;
if (pUnkOuter)
pNullRenderer->outer_unk = pUnkOuter;
else
pNullRenderer->outer_unk = &pNullRenderer->IUnknown_inner;
hr = BaseRenderer_Init(&pNullRenderer->renderer, &NullRenderer_Vtbl, pUnkOuter,
&CLSID_NullRenderer, (DWORD_PTR)(__FILE__ ": NullRendererImpl.csFilter"),
&RendererFuncTable);
if (FAILED(hr))
{
BaseRendererImpl_Release(&pNullRenderer->renderer.filter.IBaseFilter_iface);
CoTaskMemFree(pNullRenderer);
}
else
*ppv = &pNullRenderer->IUnknown_inner;
return S_OK;
}

View file

@ -20,7 +20,6 @@
*/
#include "quartz_private.h"
#include "control_private.h"
#include "pin.h"
//#include "vfwmsgs.h"
@ -41,44 +40,76 @@ static const IMediaSeekingVtbl Parser_Seeking_Vtbl;
static const IPinVtbl Parser_OutputPin_Vtbl;
static const IPinVtbl Parser_InputPin_Vtbl;
static HRESULT Parser_OutputPin_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt);
static HRESULT Parser_ChangeCurrent(IBaseFilter *iface);
static HRESULT Parser_ChangeStop(IBaseFilter *iface);
static HRESULT Parser_ChangeRate(IBaseFilter *iface);
static HRESULT WINAPI Parser_ChangeStart(IMediaSeeking *iface);
static HRESULT WINAPI Parser_ChangeStop(IMediaSeeking *iface);
static HRESULT WINAPI Parser_ChangeRate(IMediaSeeking *iface);
static HRESULT WINAPI Parser_OutputPin_DecideBufferSize(BaseOutputPin *iface, IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest);
static HRESULT WINAPI Parser_OutputPin_GetMediaType(BasePin *iface, int iPosition, AM_MEDIA_TYPE *pmt);
static HRESULT WINAPI Parser_OutputPin_DecideAllocator(BaseOutputPin *This, IMemInputPin *pPin, IMemAllocator **pAlloc);
static HRESULT WINAPI Parser_OutputPin_BreakConnect(BaseOutputPin *This);
static inline ParserImpl *impl_from_IMediaSeeking( IMediaSeeking *iface )
{
return (ParserImpl *)((char*)iface - FIELD_OFFSET(ParserImpl, mediaSeeking.lpVtbl));
return CONTAINING_RECORD(iface, ParserImpl, sourceSeeking.IMediaSeeking_iface);
}
static inline ParserImpl *impl_from_IBaseFilter( IBaseFilter *iface )
{
return CONTAINING_RECORD(iface, ParserImpl, filter.IBaseFilter_iface);
}
HRESULT Parser_Create(ParserImpl* pParser, const IBaseFilterVtbl *Parser_Vtbl, const CLSID* pClsid, PFN_PROCESS_SAMPLE fnProcessSample, PFN_QUERY_ACCEPT fnQueryAccept, PFN_PRE_CONNECT fnPreConnect, PFN_CLEANUP fnCleanup, PFN_DISCONNECT fnDisconnect, REQUESTPROC fnRequest, STOPPROCESSPROC fnDone, CHANGEPROC stop, CHANGEPROC current, CHANGEPROC rate)
static inline ParserImpl *impl_from_BaseFilter( BaseFilter *iface )
{
return CONTAINING_RECORD(iface, ParserImpl, filter);
}
/* FIXME: WRONG */
static IPin* WINAPI Parser_GetPin(BaseFilter *iface, int pos)
{
ParserImpl *This = impl_from_BaseFilter(iface);
TRACE("Asking for pos %x\n", pos);
/* Input pin also has a pin, hence the > and not >= */
if (pos > This->cStreams || pos < 0)
return NULL;
IPin_AddRef(This->ppPins[pos]);
return This->ppPins[pos];
}
static LONG WINAPI Parser_GetPinCount(BaseFilter *iface)
{
ParserImpl *This = impl_from_BaseFilter(iface);
return This->cStreams;
}
static const BaseFilterFuncTable BaseFuncTable = {
Parser_GetPin,
Parser_GetPinCount
};
HRESULT Parser_Create(ParserImpl* pParser, const IBaseFilterVtbl *Parser_Vtbl, const CLSID* pClsid, PFN_PROCESS_SAMPLE fnProcessSample, PFN_QUERY_ACCEPT fnQueryAccept, PFN_PRE_CONNECT fnPreConnect, PFN_CLEANUP fnCleanup, PFN_DISCONNECT fnDisconnect, REQUESTPROC fnRequest, STOPPROCESSPROC fnDone, SourceSeeking_ChangeStop stop, SourceSeeking_ChangeStart start, SourceSeeking_ChangeRate rate)
{
HRESULT hr;
PIN_INFO piInput;
/* pTransformFilter is already allocated */
pParser->clsid = *pClsid;
pParser->lpVtbl = Parser_Vtbl;
pParser->refCount = 1;
InitializeCriticalSection(&pParser->csFilter);
pParser->csFilter.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ParserImpl.csFilter");
pParser->state = State_Stopped;
pParser->pClock = NULL;
BaseFilter_Init(&pParser->filter, Parser_Vtbl, pClsid, (DWORD_PTR)(__FILE__ ": ParserImpl.csFilter"), &BaseFuncTable);
pParser->fnDisconnect = fnDisconnect;
ZeroMemory(&pParser->filterInfo, sizeof(FILTER_INFO));
pParser->lastpinchange = GetTickCount();
pParser->cStreams = 0;
pParser->ppPins = CoTaskMemAlloc(1 * sizeof(IPin *));
/* construct input pin */
piInput.dir = PINDIR_INPUT;
piInput.pFilter = (IBaseFilter *)pParser;
piInput.pFilter = &pParser->filter.IBaseFilter_iface;
lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
if (!current)
current = Parser_ChangeCurrent;
if (!start)
start = Parser_ChangeStart;
if (!stop)
stop = Parser_ChangeStop;
@ -86,21 +117,19 @@ HRESULT Parser_Create(ParserImpl* pParser, const IBaseFilterVtbl *Parser_Vtbl, c
if (!rate)
rate = Parser_ChangeRate;
MediaSeekingImpl_Init((IBaseFilter*)pParser, stop, current, rate, &pParser->mediaSeeking, &pParser->csFilter);
pParser->mediaSeeking.lpVtbl = &Parser_Seeking_Vtbl;
SourceSeeking_Init(&pParser->sourceSeeking, &Parser_Seeking_Vtbl, stop, start, rate, &pParser->filter.csFilter);
hr = PullPin_Construct(&Parser_InputPin_Vtbl, &piInput, fnProcessSample, (LPVOID)pParser, fnQueryAccept, fnCleanup, fnRequest, fnDone, &pParser->csFilter, (IPin **)&pParser->pInputPin);
hr = PullPin_Construct(&Parser_InputPin_Vtbl, &piInput, fnProcessSample, (LPVOID)pParser, fnQueryAccept, fnCleanup, fnRequest, fnDone, &pParser->filter.csFilter, (IPin **)&pParser->pInputPin);
if (SUCCEEDED(hr))
{
pParser->ppPins[0] = (IPin *)pParser->pInputPin;
pParser->ppPins[0] = &pParser->pInputPin->pin.IPin_iface;
pParser->pInputPin->fnPreConnect = fnPreConnect;
}
else
{
CoTaskMemFree(pParser->ppPins);
pParser->csFilter.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&pParser->csFilter);
BaseFilterImpl_Release(&pParser->filter.IBaseFilter_iface);
CoTaskMemFree(pParser);
}
@ -109,21 +138,16 @@ HRESULT Parser_Create(ParserImpl* pParser, const IBaseFilterVtbl *Parser_Vtbl, c
HRESULT WINAPI Parser_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv)
{
ParserImpl *This = (ParserImpl *)iface;
ParserImpl *This = impl_from_IBaseFilter(iface);
TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv);
*ppv = NULL;
if (IsEqualIID(riid, &IID_IUnknown))
if ( IsEqualIID(riid, &IID_IUnknown)
|| IsEqualIID(riid, &IID_IPersist)
|| IsEqualIID(riid, &IID_IMediaFilter)
|| IsEqualIID(riid, &IID_IBaseFilter) )
*ppv = This;
else if (IsEqualIID(riid, &IID_IPersist))
*ppv = This;
else if (IsEqualIID(riid, &IID_IMediaFilter))
*ppv = This;
else if (IsEqualIID(riid, &IID_IBaseFilter))
*ppv = This;
else if (IsEqualIID(riid, &IID_IMediaSeeking))
*ppv = &This->mediaSeeking;
if (*ppv)
{
@ -139,12 +163,7 @@ HRESULT WINAPI Parser_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID *
ULONG WINAPI Parser_AddRef(IBaseFilter * iface)
{
ParserImpl *This = (ParserImpl *)iface;
ULONG refCount = InterlockedIncrement(&This->refCount);
TRACE("(%p/%p)->() AddRef from %d\n", This, iface, refCount - 1);
return refCount;
return BaseFilterImpl_AddRef(iface);
}
void Parser_Destroy(ParserImpl *This)
@ -152,21 +171,18 @@ void Parser_Destroy(ParserImpl *This)
IPin *connected = NULL;
ULONG pinref;
assert(!This->refCount);
assert(!This->filter.refCount);
PullPin_WaitForStateChange(This->pInputPin, INFINITE);
if (This->pClock)
IReferenceClock_Release(This->pClock);
/* Don't need to clean up output pins, freeing input pin will do that */
IPin_ConnectedTo((IPin *)This->pInputPin, &connected);
IPin_ConnectedTo(&This->pInputPin->pin.IPin_iface, &connected);
if (connected)
{
assert(IPin_Disconnect(connected) == S_OK);
IPin_Release(connected);
assert(IPin_Disconnect((IPin *)This->pInputPin) == S_OK);
assert(IPin_Disconnect(&This->pInputPin->pin.IPin_iface) == S_OK);
}
pinref = IPin_Release((IPin *)This->pInputPin);
pinref = IPin_Release(&This->pInputPin->pin.IPin_iface);
if (pinref)
{
/* Valgrind could find this, if I kill it here */
@ -174,14 +190,10 @@ void Parser_Destroy(ParserImpl *This)
assert((LONG)pinref > 0);
while (pinref)
pinref = IPin_Release((IPin *)This->pInputPin);
pinref = IPin_Release(&This->pInputPin->pin.IPin_iface);
}
CoTaskMemFree(This->ppPins);
This->lpVtbl = NULL;
This->csFilter.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&This->csFilter);
TRACE("Destroying parser\n");
CoTaskMemFree(This);
@ -189,8 +201,8 @@ void Parser_Destroy(ParserImpl *This)
ULONG WINAPI Parser_Release(IBaseFilter * iface)
{
ParserImpl *This = (ParserImpl *)iface;
ULONG refCount = InterlockedDecrement(&This->refCount);
ParserImpl *This = impl_from_IBaseFilter(iface);
ULONG refCount = BaseFilterImpl_Release(iface);
TRACE("(%p)->() Release from %d\n", This, refCount + 1);
@ -204,11 +216,11 @@ ULONG WINAPI Parser_Release(IBaseFilter * iface)
HRESULT WINAPI Parser_GetClassID(IBaseFilter * iface, CLSID * pClsid)
{
ParserImpl *This = (ParserImpl *)iface;
ParserImpl *This = impl_from_IBaseFilter(iface);
TRACE("(%p)\n", pClsid);
*pClsid = This->clsid;
*pClsid = This->filter.clsid;
return S_OK;
}
@ -217,8 +229,8 @@ HRESULT WINAPI Parser_GetClassID(IBaseFilter * iface, CLSID * pClsid)
HRESULT WINAPI Parser_Stop(IBaseFilter * iface)
{
ParserImpl *This = (ParserImpl *)iface;
PullPin *pin = (PullPin *)This->ppPins[0];
ParserImpl *This = impl_from_IBaseFilter(iface);
PullPin *pin = impl_PullPin_from_IPin(This->ppPins[0]);
ULONG i;
TRACE("()\n");
@ -226,24 +238,24 @@ HRESULT WINAPI Parser_Stop(IBaseFilter * iface)
EnterCriticalSection(&pin->thread_lock);
IAsyncReader_BeginFlush(This->pInputPin->pReader);
EnterCriticalSection(&This->csFilter);
EnterCriticalSection(&This->filter.csFilter);
if (This->state == State_Stopped)
if (This->filter.state == State_Stopped)
{
LeaveCriticalSection(&This->csFilter);
LeaveCriticalSection(&This->filter.csFilter);
IAsyncReader_EndFlush(This->pInputPin->pReader);
LeaveCriticalSection(&pin->thread_lock);
return S_OK;
}
This->state = State_Stopped;
This->filter.state = State_Stopped;
for (i = 1; i < (This->cStreams + 1); i++)
{
OutputPin_DecommitAllocator((OutputPin *)This->ppPins[i]);
BaseOutputPinImpl_Inactive((BaseOutputPin *)This->ppPins[i]);
}
LeaveCriticalSection(&This->csFilter);
LeaveCriticalSection(&This->filter.csFilter);
PullPin_PauseProcessing(This->pInputPin);
PullPin_WaitForStateChange(This->pInputPin, INFINITE);
@ -256,32 +268,32 @@ HRESULT WINAPI Parser_Stop(IBaseFilter * iface)
HRESULT WINAPI Parser_Pause(IBaseFilter * iface)
{
HRESULT hr = S_OK;
ParserImpl *This = (ParserImpl *)iface;
PullPin *pin = (PullPin *)This->ppPins[0];
ParserImpl *This = impl_from_IBaseFilter(iface);
PullPin *pin = impl_PullPin_from_IPin(This->ppPins[0]);
TRACE("()\n");
EnterCriticalSection(&pin->thread_lock);
EnterCriticalSection(&This->csFilter);
EnterCriticalSection(&This->filter.csFilter);
if (This->state == State_Paused)
if (This->filter.state == State_Paused)
{
LeaveCriticalSection(&This->csFilter);
LeaveCriticalSection(&This->filter.csFilter);
LeaveCriticalSection(&pin->thread_lock);
return S_OK;
}
if (This->state == State_Stopped)
if (This->filter.state == State_Stopped)
{
LeaveCriticalSection(&This->csFilter);
LeaveCriticalSection(&This->filter.csFilter);
hr = IBaseFilter_Run(iface, -1);
EnterCriticalSection(&This->csFilter);
EnterCriticalSection(&This->filter.csFilter);
}
if (SUCCEEDED(hr))
This->state = State_Paused;
This->filter.state = State_Paused;
LeaveCriticalSection(&This->csFilter);
LeaveCriticalSection(&This->filter.csFilter);
LeaveCriticalSection(&pin->thread_lock);
return hr;
@ -290,31 +302,30 @@ HRESULT WINAPI Parser_Pause(IBaseFilter * iface)
HRESULT WINAPI Parser_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
{
HRESULT hr = S_OK;
ParserImpl *This = (ParserImpl *)iface;
PullPin *pin = (PullPin *)This->ppPins[0];
ParserImpl *This = impl_from_IBaseFilter(iface);
PullPin *pin = impl_PullPin_from_IPin(This->ppPins[0]);
ULONG i;
TRACE("(%s)\n", wine_dbgstr_longlong(tStart));
EnterCriticalSection(&pin->thread_lock);
EnterCriticalSection(&This->csFilter);
EnterCriticalSection(&This->filter.csFilter);
{
HRESULT hr_any = VFW_E_NOT_CONNECTED;
if (This->state == State_Running || This->state == State_Paused)
This->filter.rtStreamStart = tStart;
if (This->filter.state == State_Running || This->filter.state == State_Paused)
{
This->state = State_Running;
LeaveCriticalSection(&This->csFilter);
This->filter.state = State_Running;
LeaveCriticalSection(&This->filter.csFilter);
LeaveCriticalSection(&pin->thread_lock);
return S_OK;
}
This->rtStreamStart = tStart;
for (i = 1; i < (This->cStreams + 1); i++)
{
hr = OutputPin_CommitAllocator((OutputPin *)This->ppPins[i]);
hr = BaseOutputPinImpl_Active((BaseOutputPin *)This->ppPins[i]);
if (SUCCEEDED(hr))
hr_any = hr;
}
@ -322,15 +333,15 @@ HRESULT WINAPI Parser_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
hr = hr_any;
if (SUCCEEDED(hr))
{
LeaveCriticalSection(&This->csFilter);
LeaveCriticalSection(&This->filter.csFilter);
hr = PullPin_StartProcessing(This->pInputPin);
EnterCriticalSection(&This->csFilter);
EnterCriticalSection(&This->filter.csFilter);
}
if (SUCCEEDED(hr))
This->state = State_Running;
This->filter.state = State_Running;
}
LeaveCriticalSection(&This->csFilter);
LeaveCriticalSection(&This->filter.csFilter);
LeaveCriticalSection(&pin->thread_lock);
return hr;
@ -338,18 +349,18 @@ HRESULT WINAPI Parser_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
HRESULT WINAPI Parser_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
{
ParserImpl *This = (ParserImpl *)iface;
PullPin *pin = (PullPin *)This->ppPins[0];
ParserImpl *This = impl_from_IBaseFilter(iface);
PullPin *pin = impl_PullPin_from_IPin(This->ppPins[0]);
HRESULT hr = S_OK;
TRACE("(%d, %p)\n", dwMilliSecsTimeout, pState);
EnterCriticalSection(&pin->thread_lock);
EnterCriticalSection(&This->csFilter);
EnterCriticalSection(&This->filter.csFilter);
{
*pState = This->state;
*pState = This->filter.state;
}
LeaveCriticalSection(&This->csFilter);
LeaveCriticalSection(&This->filter.csFilter);
if (This->pInputPin && (PullPin_WaitForStateChange(This->pInputPin, dwMilliSecsTimeout) == S_FALSE))
hr = VFW_S_STATE_INTERMEDIATE;
@ -360,21 +371,13 @@ HRESULT WINAPI Parser_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FI
HRESULT WINAPI Parser_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock)
{
ParserImpl *This = (ParserImpl *)iface;
PullPin *pin = (PullPin *)This->ppPins[0];
ParserImpl *This = impl_from_IBaseFilter(iface);
PullPin *pin = impl_PullPin_from_IPin(This->ppPins[0]);
TRACE("(%p)\n", pClock);
EnterCriticalSection(&pin->thread_lock);
EnterCriticalSection(&This->csFilter);
{
if (This->pClock)
IReferenceClock_Release(This->pClock);
This->pClock = pClock;
if (This->pClock)
IReferenceClock_AddRef(This->pClock);
}
LeaveCriticalSection(&This->csFilter);
BaseFilterImpl_SetSyncSource(iface,pClock);
LeaveCriticalSection(&pin->thread_lock);
return S_OK;
@ -382,48 +385,14 @@ HRESULT WINAPI Parser_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock
HRESULT WINAPI Parser_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock)
{
ParserImpl *This = (ParserImpl *)iface;
TRACE("(%p)\n", ppClock);
EnterCriticalSection(&This->csFilter);
{
*ppClock = This->pClock;
if (This->pClock)
IReferenceClock_AddRef(This->pClock);
}
LeaveCriticalSection(&This->csFilter);
return S_OK;
return BaseFilterImpl_GetSyncSource(iface, ppClock);
}
/** IBaseFilter implementation **/
/* FIXME: WRONG */
static HRESULT Parser_GetPin(IBaseFilter *iface, ULONG pos, IPin **pin, DWORD *lastsynctick)
{
ParserImpl *This = (ParserImpl *)iface;
*lastsynctick = This->lastpinchange;
TRACE("Asking for pos %x\n", pos);
/* Input pin also has a pin, hence the > and not >= */
if (pos > This->cStreams)
return S_FALSE;
*pin = This->ppPins[pos];
IPin_AddRef(*pin);
return S_OK;
}
HRESULT WINAPI Parser_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum)
{
ParserImpl *This = (ParserImpl *)iface;
TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
return IEnumPinsImpl_Construct(ppEnum, Parser_GetPin, iface);
return BaseFilterImpl_EnumPins(iface,ppEnum);
}
HRESULT WINAPI Parser_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
@ -437,45 +406,32 @@ HRESULT WINAPI Parser_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
HRESULT WINAPI Parser_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo)
{
ParserImpl *This = (ParserImpl *)iface;
TRACE("(%p)\n", pInfo);
strcpyW(pInfo->achName, This->filterInfo.achName);
pInfo->pGraph = This->filterInfo.pGraph;
if (pInfo->pGraph)
IFilterGraph_AddRef(pInfo->pGraph);
return S_OK;
return BaseFilterImpl_QueryFilterInfo(iface, pInfo);
}
HRESULT WINAPI Parser_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName)
{
HRESULT hr = S_OK;
ParserImpl *This = (ParserImpl *)iface;
TRACE("(%p, %s)\n", pGraph, debugstr_w(pName));
EnterCriticalSection(&This->csFilter);
{
if (pName)
strcpyW(This->filterInfo.achName, pName);
else
*This->filterInfo.achName = '\0';
This->filterInfo.pGraph = pGraph; /* NOTE: do NOT increase ref. count */
}
LeaveCriticalSection(&This->csFilter);
return hr;
return BaseFilterImpl_JoinFilterGraph(iface, pGraph, pName);
}
HRESULT WINAPI Parser_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo)
{
TRACE("(%p)\n", pVendorInfo);
return E_NOTIMPL;
return BaseFilterImpl_QueryVendorInfo(iface, pVendorInfo);
}
static const BasePinFuncTable output_BaseFuncTable = {
NULL,
BaseOutputPinImpl_AttemptConnection,
BasePinImpl_GetMediaTypeVersion,
Parser_OutputPin_GetMediaType
};
static const BaseOutputPinFuncTable output_BaseOutputFuncTable = {
Parser_OutputPin_DecideBufferSize,
Parser_OutputPin_DecideAllocator,
Parser_OutputPin_BreakConnect
};
HRESULT Parser_AddPin(ParserImpl * This, const PIN_INFO * piOutput, ALLOCATOR_PROPERTIES * props, const AM_MEDIA_TYPE * amt)
{
IPin ** ppOldPins;
@ -486,21 +442,20 @@ HRESULT Parser_AddPin(ParserImpl * This, const PIN_INFO * piOutput, ALLOCATOR_PR
This->ppPins = CoTaskMemAlloc((This->cStreams + 2) * sizeof(IPin *));
memcpy(This->ppPins, ppOldPins, (This->cStreams + 1) * sizeof(IPin *));
hr = OutputPin_Construct(&Parser_OutputPin_Vtbl, sizeof(Parser_OutputPin), piOutput, props, NULL, Parser_OutputPin_QueryAccept, &This->csFilter, This->ppPins + (This->cStreams + 1));
hr = BaseOutputPin_Construct(&Parser_OutputPin_Vtbl, sizeof(Parser_OutputPin), piOutput, &output_BaseFuncTable, &output_BaseOutputFuncTable, &This->filter.csFilter, This->ppPins + (This->cStreams + 1));
if (SUCCEEDED(hr))
{
IPin *pPin = This->ppPins[This->cStreams + 1];
Parser_OutputPin *pin = (Parser_OutputPin *)pPin;
Parser_OutputPin *pin = unsafe_impl_Parser_OutputPin_from_IPin(pPin);
pin->pmt = CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
CopyMediaType(pin->pmt, amt);
pin->dwSamplesProcessed = 0;
pin->pin.pin.pUserData = This->ppPins[This->cStreams + 1];
pin->pin.pin.pinInfo.pFilter = (LPVOID)This;
pin->pin.custom_allocator = 1;
pin->allocProps = *props;
This->cStreams++;
This->lastpinchange = GetTickCount();
BaseFilterImpl_IncrementPinVersion(&This->filter);
CoTaskMemFree(ppOldPins);
}
else
@ -528,31 +483,31 @@ static HRESULT Parser_RemoveOutputPins(ParserImpl * This)
for (i = 0; i < This->cStreams; i++)
{
hr = OutputPin_DeliverDisconnect((OutputPin *)ppOldPins[i + 1]);
hr = ((BaseOutputPin *)ppOldPins[i + 1])->pFuncsTable->pfnBreakConnect((BaseOutputPin *)ppOldPins[i + 1]);
TRACE("Disconnect: %08x\n", hr);
IPin_Release(ppOldPins[i + 1]);
}
This->lastpinchange = GetTickCount();
BaseFilterImpl_IncrementPinVersion(&This->filter);
This->cStreams = 0;
CoTaskMemFree(ppOldPins);
return S_OK;
}
static HRESULT Parser_ChangeCurrent(IBaseFilter *iface)
static HRESULT WINAPI Parser_ChangeStart(IMediaSeeking *iface)
{
FIXME("(%p) filter hasn't implemented current position change!\n", iface);
FIXME("(%p) filter hasn't implemented start position change!\n", iface);
return S_OK;
}
static HRESULT Parser_ChangeStop(IBaseFilter *iface)
static HRESULT WINAPI Parser_ChangeStop(IMediaSeeking *iface)
{
FIXME("(%p) filter hasn't implemented stop position change!\n", iface);
return S_OK;
}
static HRESULT Parser_ChangeRate(IBaseFilter *iface)
static HRESULT WINAPI Parser_ChangeRate(IMediaSeeking *iface)
{
FIXME("(%p) filter hasn't implemented rate change!\n", iface);
return S_OK;
@ -585,28 +540,98 @@ static const IMediaSeekingVtbl Parser_Seeking_Vtbl =
Parser_Seeking_QueryInterface,
Parser_Seeking_AddRef,
Parser_Seeking_Release,
MediaSeekingImpl_GetCapabilities,
MediaSeekingImpl_CheckCapabilities,
MediaSeekingImpl_IsFormatSupported,
MediaSeekingImpl_QueryPreferredFormat,
MediaSeekingImpl_GetTimeFormat,
MediaSeekingImpl_IsUsingTimeFormat,
MediaSeekingImpl_SetTimeFormat,
MediaSeekingImpl_GetDuration,
MediaSeekingImpl_GetStopPosition,
MediaSeekingImpl_GetCurrentPosition,
MediaSeekingImpl_ConvertTimeFormat,
MediaSeekingImpl_SetPositions,
MediaSeekingImpl_GetPositions,
MediaSeekingImpl_GetAvailable,
MediaSeekingImpl_SetRate,
MediaSeekingImpl_GetRate,
MediaSeekingImpl_GetPreroll
SourceSeekingImpl_GetCapabilities,
SourceSeekingImpl_CheckCapabilities,
SourceSeekingImpl_IsFormatSupported,
SourceSeekingImpl_QueryPreferredFormat,
SourceSeekingImpl_GetTimeFormat,
SourceSeekingImpl_IsUsingTimeFormat,
SourceSeekingImpl_SetTimeFormat,
SourceSeekingImpl_GetDuration,
SourceSeekingImpl_GetStopPosition,
SourceSeekingImpl_GetCurrentPosition,
SourceSeekingImpl_ConvertTimeFormat,
SourceSeekingImpl_SetPositions,
SourceSeekingImpl_GetPositions,
SourceSeekingImpl_GetAvailable,
SourceSeekingImpl_SetRate,
SourceSeekingImpl_GetRate,
SourceSeekingImpl_GetPreroll
};
static HRESULT WINAPI Parser_OutputPin_DecideBufferSize(BaseOutputPin *iface, IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest)
{
Parser_OutputPin *This = (Parser_OutputPin*)iface;
ALLOCATOR_PROPERTIES actual;
if (ppropInputRequest->cbAlign && ppropInputRequest->cbAlign != This->allocProps.cbAlign)
FIXME("Requested Buffer cbAlign mismatch %i,%i\n",This->allocProps.cbAlign, ppropInputRequest->cbAlign);
if (ppropInputRequest->cbPrefix)
FIXME("Requested Buffer cbPrefix mismatch %i,%i\n",This->allocProps.cbPrefix, ppropInputRequest->cbPrefix);
if (ppropInputRequest->cbBuffer)
FIXME("Requested Buffer cbBuffer mismatch %i,%i\n",This->allocProps.cbBuffer, ppropInputRequest->cbBuffer);
if (ppropInputRequest->cBuffers)
FIXME("Requested Buffer cBuffers mismatch %i,%i\n",This->allocProps.cBuffers, ppropInputRequest->cBuffers);
return IMemAllocator_SetProperties(pAlloc, &This->allocProps, &actual);
}
static HRESULT WINAPI Parser_OutputPin_GetMediaType(BasePin *iface, int iPosition, AM_MEDIA_TYPE *pmt)
{
Parser_OutputPin *This = (Parser_OutputPin*)iface;
if (iPosition < 0)
return E_INVALIDARG;
if (iPosition > 0)
return VFW_S_NO_MORE_ITEMS;
CopyMediaType(pmt, This->pmt);
return S_OK;
}
static HRESULT WINAPI Parser_OutputPin_DecideAllocator(BaseOutputPin *iface, IMemInputPin *pPin, IMemAllocator **pAlloc)
{
Parser_OutputPin *This = (Parser_OutputPin*)iface;
HRESULT hr;
*pAlloc = NULL;
if (This->alloc)
{
hr = IMemInputPin_NotifyAllocator(pPin, This->alloc, This->readonly);
if (SUCCEEDED(hr))
{
*pAlloc = This->alloc;
IMemAllocator_AddRef(*pAlloc);
}
}
else
hr = VFW_E_NO_ALLOCATOR;
return hr;
}
static HRESULT WINAPI Parser_OutputPin_BreakConnect(BaseOutputPin *This)
{
HRESULT hr;
TRACE("(%p)->()\n", This);
EnterCriticalSection(This->pin.pCritSec);
if (!This->pin.pConnectedTo || !This->pMemInputPin)
hr = VFW_E_NOT_CONNECTED;
else
{
hr = IPin_Disconnect(This->pin.pConnectedTo);
IPin_Disconnect(&This->pin.IPin_iface);
}
LeaveCriticalSection(This->pin.pCritSec);
return hr;
}
static HRESULT WINAPI Parser_OutputPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv)
{
Parser_OutputPin *This = (Parser_OutputPin *)iface;
Parser_OutputPin *This = unsafe_impl_Parser_OutputPin_from_IPin(iface);
TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv);
@ -616,10 +641,9 @@ static HRESULT WINAPI Parser_OutputPin_QueryInterface(IPin * iface, REFIID riid,
*ppv = iface;
else if (IsEqualIID(riid, &IID_IPin))
*ppv = iface;
/* The Parser filter does not support querying IMediaSeeking, return it directly */
else if (IsEqualIID(riid, &IID_IMediaSeeking))
{
return IBaseFilter_QueryInterface(This->pin.pin.pinInfo.pFilter, &IID_IMediaSeeking, ppv);
}
*ppv = &impl_from_IBaseFilter(This->pin.pin.pinInfo.pFilter)->sourceSeeking;
if (*ppv)
{
@ -634,7 +658,7 @@ static HRESULT WINAPI Parser_OutputPin_QueryInterface(IPin * iface, REFIID riid,
static ULONG WINAPI Parser_OutputPin_Release(IPin * iface)
{
Parser_OutputPin *This = (Parser_OutputPin *)iface;
Parser_OutputPin *This = unsafe_impl_Parser_OutputPin_from_IPin(iface);
ULONG refCount = InterlockedDecrement(&This->pin.pin.refCount);
TRACE("(%p)->() Release from %d\n", iface, refCount + 1);
@ -644,42 +668,30 @@ static ULONG WINAPI Parser_OutputPin_Release(IPin * iface)
FreeMediaType(This->pmt);
CoTaskMemFree(This->pmt);
FreeMediaType(&This->pin.pin.mtCurrent);
if (This->pin.pAllocator)
IMemAllocator_Release(This->pin.pAllocator);
CoTaskMemFree(This);
return 0;
}
return refCount;
}
static HRESULT WINAPI Parser_OutputPin_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum)
{
ENUMMEDIADETAILS emd;
Parser_OutputPin *This = (Parser_OutputPin *)iface;
TRACE("(%p)\n", ppEnum);
/* override this method to allow enumeration of your types */
emd.cMediaTypes = 1;
emd.pMediaTypes = This->pmt;
return IEnumMediaTypesImpl_Construct(&emd, ppEnum);
}
static HRESULT WINAPI Parser_OutputPin_Connect(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
{
Parser_OutputPin *This = (Parser_OutputPin *)iface;
ParserImpl *parser = (ParserImpl *)This->pin.pin.pinInfo.pFilter;
Parser_OutputPin *This = unsafe_impl_Parser_OutputPin_from_IPin(iface);
ParserImpl *parser = impl_from_IBaseFilter(This->pin.pin.pinInfo.pFilter);
/* Set the allocator to our input pin's */
EnterCriticalSection(This->pin.pin.pCritSec);
This->pin.alloc = parser->pInputPin->pAlloc;
This->alloc = parser->pInputPin->pAlloc;
LeaveCriticalSection(This->pin.pin.pCritSec);
return OutputPin_Connect(iface, pReceivePin, pmt);
return BaseOutputPinImpl_Connect(iface, pReceivePin, pmt);
}
static HRESULT Parser_OutputPin_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt)
static HRESULT WINAPI Parser_OutputPin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE * pmt)
{
Parser_OutputPin *This = iface;
Parser_OutputPin *This = unsafe_impl_Parser_OutputPin_from_IPin(iface);
TRACE("()\n");
dump_AM_MEDIA_TYPE(pmt);
@ -690,29 +702,54 @@ static HRESULT Parser_OutputPin_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE *
static const IPinVtbl Parser_OutputPin_Vtbl =
{
Parser_OutputPin_QueryInterface,
IPinImpl_AddRef,
BasePinImpl_AddRef,
Parser_OutputPin_Release,
Parser_OutputPin_Connect,
OutputPin_ReceiveConnection,
OutputPin_Disconnect,
IPinImpl_ConnectedTo,
IPinImpl_ConnectionMediaType,
IPinImpl_QueryPinInfo,
IPinImpl_QueryDirection,
IPinImpl_QueryId,
IPinImpl_QueryAccept,
Parser_OutputPin_EnumMediaTypes,
IPinImpl_QueryInternalConnections,
OutputPin_EndOfStream,
OutputPin_BeginFlush,
OutputPin_EndFlush,
OutputPin_NewSegment
BaseOutputPinImpl_ReceiveConnection,
BaseOutputPinImpl_Disconnect,
BasePinImpl_ConnectedTo,
BasePinImpl_ConnectionMediaType,
BasePinImpl_QueryPinInfo,
BasePinImpl_QueryDirection,
BasePinImpl_QueryId,
Parser_OutputPin_QueryAccept,
BasePinImpl_EnumMediaTypes,
BasePinImpl_QueryInternalConnections,
BaseOutputPinImpl_EndOfStream,
BaseOutputPinImpl_BeginFlush,
BaseOutputPinImpl_EndFlush,
BasePinImpl_NewSegment
};
static HRESULT WINAPI Parser_PullPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv)
{
PullPin *This = impl_PullPin_from_IPin(iface);
TRACE("(%p/%p)->(%s, %p)\n", This, iface, qzdebugstr_guid(riid), ppv);
*ppv = NULL;
/*
* It is important to capture the request for the IMediaSeeking interface before it is passed
* on to PullPin_QueryInterface, this is necessary since the Parser filter does not support
* querying IMediaSeeking
*/
if (IsEqualIID(riid, &IID_IMediaSeeking))
*ppv = &impl_from_IBaseFilter(This->pin.pinInfo.pFilter)->sourceSeeking;
if (*ppv)
{
IUnknown_AddRef((IUnknown *)(*ppv));
return S_OK;
}
return PullPin_QueryInterface(iface, riid, ppv);
}
static HRESULT WINAPI Parser_PullPin_Disconnect(IPin * iface)
{
HRESULT hr;
PullPin *This = (PullPin *)iface;
PullPin *This = impl_PullPin_from_IPin(iface);
TRACE("()\n");
@ -722,7 +759,7 @@ static HRESULT WINAPI Parser_PullPin_Disconnect(IPin * iface)
if (This->pin.pConnectedTo)
{
FILTER_STATE state;
ParserImpl *Parser = (ParserImpl *)This->pin.pinInfo.pFilter;
ParserImpl *Parser = impl_from_IBaseFilter(This->pin.pinInfo.pFilter);
LeaveCriticalSection(This->pin.pCritSec);
hr = IBaseFilter_GetState(This->pin.pinInfo.pFilter, INFINITE, &state);
@ -733,7 +770,7 @@ static HRESULT WINAPI Parser_PullPin_Disconnect(IPin * iface)
LeaveCriticalSection(This->pin.pCritSec);
PullPin_Disconnect(iface);
EnterCriticalSection(This->pin.pCritSec);
hr = Parser_RemoveOutputPins((ParserImpl *)This->pin.pinInfo.pFilter);
hr = Parser_RemoveOutputPins(impl_from_IBaseFilter(This->pin.pinInfo.pFilter));
}
else
hr = VFW_E_NOT_STOPPED;
@ -756,32 +793,41 @@ static HRESULT WINAPI Parser_PullPin_ReceiveConnection(IPin * iface, IPin * pRec
hr = PullPin_ReceiveConnection(iface, pReceivePin, pmt);
if (FAILED(hr))
{
IPinImpl *This = (IPinImpl *)iface;
BasePin *This = (BasePin *)iface;
EnterCriticalSection(This->pCritSec);
Parser_RemoveOutputPins((ParserImpl *)This->pinInfo.pFilter);
Parser_RemoveOutputPins(impl_from_IBaseFilter(This->pinInfo.pFilter));
LeaveCriticalSection(This->pCritSec);
}
return hr;
}
static HRESULT WINAPI Parser_PullPin_EnumMediaTypes(IPin *iface, IEnumMediaTypes **ppEnum)
{
BasePin *This = (BasePin *)iface;
TRACE("(%p/%p)->(%p)\n", This, iface, ppEnum);
return EnumMediaTypes_Construct(This, BasePinImpl_GetMediaType, BasePinImpl_GetMediaTypeVersion, ppEnum);
}
static const IPinVtbl Parser_InputPin_Vtbl =
{
PullPin_QueryInterface,
IPinImpl_AddRef,
Parser_PullPin_QueryInterface,
BasePinImpl_AddRef,
PullPin_Release,
InputPin_Connect,
BaseInputPinImpl_Connect,
Parser_PullPin_ReceiveConnection,
Parser_PullPin_Disconnect,
IPinImpl_ConnectedTo,
IPinImpl_ConnectionMediaType,
IPinImpl_QueryPinInfo,
IPinImpl_QueryDirection,
IPinImpl_QueryId,
IPinImpl_QueryAccept,
IPinImpl_EnumMediaTypes,
IPinImpl_QueryInternalConnections,
BasePinImpl_ConnectedTo,
BasePinImpl_ConnectionMediaType,
BasePinImpl_QueryPinInfo,
BasePinImpl_QueryDirection,
BasePinImpl_QueryId,
PullPin_QueryAccept,
Parser_PullPin_EnumMediaTypes,
BasePinImpl_QueryInternalConnections,
PullPin_EndOfStream,
PullPin_BeginFlush,
PullPin_EndFlush,

View file

@ -28,37 +28,33 @@ typedef HRESULT (*PFN_DISCONNECT) (LPVOID iface);
struct ParserImpl
{
const IBaseFilterVtbl *lpVtbl;
BaseFilter filter;
LONG refCount;
CRITICAL_SECTION csFilter;
FILTER_STATE state;
REFERENCE_TIME rtStreamStart;
IReferenceClock * pClock;
PFN_CLEANUP fnCleanup;
PFN_DISCONNECT fnDisconnect;
FILTER_INFO filterInfo;
CLSID clsid;
PullPin * pInputPin;
IPin ** ppPins;
ULONG cStreams;
DWORD lastpinchange;
MediaSeekingImpl mediaSeeking;
SourceSeeking sourceSeeking;
};
typedef struct Parser_OutputPin
{
OutputPin pin;
BaseOutputPin pin;
AM_MEDIA_TYPE * pmt;
LONGLONG dwSamplesProcessed;
ALLOCATOR_PROPERTIES allocProps;
IMemAllocator *alloc;
BOOL readonly;
} Parser_OutputPin;
extern HRESULT Parser_AddPin(ParserImpl * This, const PIN_INFO * piOutput, ALLOCATOR_PROPERTIES * props, const AM_MEDIA_TYPE * amt);
extern HRESULT Parser_Create(ParserImpl*, const IBaseFilterVtbl *, const CLSID*, PFN_PROCESS_SAMPLE, PFN_QUERY_ACCEPT, PFN_PRE_CONNECT,
PFN_CLEANUP, PFN_DISCONNECT, REQUESTPROC, STOPPROCESSPROC, CHANGEPROC stop, CHANGEPROC current, CHANGEPROC rate);
PFN_CLEANUP, PFN_DISCONNECT, REQUESTPROC, STOPPROCESSPROC, SourceSeeking_ChangeStop stop, SourceSeeking_ChangeStart start, SourceSeeking_ChangeRate rate);
/* Override the _Release function and call this when releasing */
extern void Parser_Destroy(ParserImpl *This);
@ -78,3 +74,9 @@ extern HRESULT WINAPI Parser_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppP
extern HRESULT WINAPI Parser_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo);
extern HRESULT WINAPI Parser_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName);
extern HRESULT WINAPI Parser_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo);
/* COM helpers */
static inline Parser_OutputPin *unsafe_impl_Parser_OutputPin_from_IPin( IPin *iface )
{
return CONTAINING_RECORD(iface, Parser_OutputPin, pin.pin.IPin_iface);
}

File diff suppressed because it is too large Load diff

View file

@ -24,7 +24,6 @@
* Cookie is the cookie that was set when requesting the buffer, if you don't
* implement custom requesting, you can safely ignore this
*/
typedef HRESULT (* SAMPLEPROC_PUSH)(LPVOID userdata, IMediaSample * pSample);
typedef HRESULT (* SAMPLEPROC_PULL)(LPVOID userdata, IMediaSample * pSample, DWORD_PTR cookie);
/* This function will determine whether a type is supported or not.
@ -66,56 +65,17 @@ typedef HRESULT (* STOPPROCESSPROC) (LPVOID userdata);
#define ALIGNDOWN(value,boundary) ((value)/(boundary)*(boundary))
#define ALIGNUP(value,boundary) (ALIGNDOWN((value)+(boundary)-1, (boundary)))
typedef struct IPinImpl
{
const struct IPinVtbl * lpVtbl;
LONG refCount;
LPCRITICAL_SECTION pCritSec;
PIN_INFO pinInfo;
IPin * pConnectedTo;
AM_MEDIA_TYPE mtCurrent;
ENUMMEDIADETAILS enumMediaDetails;
QUERYACCEPTPROC fnQueryAccept;
LPVOID pUserData;
} IPinImpl;
typedef struct InputPin
{
/* inheritance C style! */
IPinImpl pin;
const IMemInputPinVtbl * lpVtblMemInput;
IMemAllocator * pAllocator;
SAMPLEPROC_PUSH fnSampleProc;
CLEANUPPROC fnCleanProc;
REFERENCE_TIME tStart;
REFERENCE_TIME tStop;
double dRate;
BOOL flushing, end_of_stream;
IMemAllocator *preferred_allocator;
} InputPin;
typedef struct OutputPin
{
/* inheritance C style! */
IPinImpl pin;
IMemInputPin * pMemInputPin;
HRESULT (* pConnectSpecific)(IPin * iface, IPin * pReceiver, const AM_MEDIA_TYPE * pmt);
BOOL custom_allocator;
IMemAllocator *alloc;
BOOL readonly;
ALLOCATOR_PROPERTIES allocProps;
} OutputPin;
typedef struct PullPin
{
/* inheritance C style! */
IPinImpl pin;
BasePin pin;
LPVOID pUserData;
REFERENCE_TIME rtStart, rtCurrent, rtNext, rtStop;
IAsyncReader * pReader;
IMemAllocator * prefAlloc;
IMemAllocator * pAlloc;
QUERYACCEPTPROC fnQueryAccept;
SAMPLEPROC_PULL fnSampleProc;
PRECONNECTPROC fnPreConnect;
REQUESTPROC fnCustomRequest;
@ -142,58 +102,18 @@ typedef struct PullPin
#define Req_Pause 3
/*** Constructors ***/
HRESULT InputPin_Construct(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PUSH pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, LPCRITICAL_SECTION pCritSec, IMemAllocator *, IPin ** ppPin);
HRESULT OutputPin_Construct(const IPinVtbl *OutputPin_Vtbl, LONG outputpin_size, const PIN_INFO * pPinInfo, ALLOCATOR_PROPERTIES *props, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, LPCRITICAL_SECTION pCritSec, IPin ** ppPin);
HRESULT PullPin_Construct(const IPinVtbl *PullPin_Vtbl, const PIN_INFO * pPinInfo, SAMPLEPROC_PULL pSampleProc, LPVOID pUserData, QUERYACCEPTPROC pQueryAccept, CLEANUPPROC pCleanUp, STOPPROCESSPROC, REQUESTPROC pCustomRequest, LPCRITICAL_SECTION pCritSec, IPin ** ppPin);
/**************************/
/*** Pin Implementation ***/
/* Common */
ULONG WINAPI IPinImpl_AddRef(IPin * iface);
HRESULT WINAPI IPinImpl_Disconnect(IPin * iface);
HRESULT WINAPI IPinImpl_ConnectedTo(IPin * iface, IPin ** ppPin);
HRESULT WINAPI IPinImpl_ConnectionMediaType(IPin * iface, AM_MEDIA_TYPE * pmt);
HRESULT WINAPI IPinImpl_QueryPinInfo(IPin * iface, PIN_INFO * pInfo);
HRESULT WINAPI IPinImpl_QueryDirection(IPin * iface, PIN_DIRECTION * pPinDir);
HRESULT WINAPI IPinImpl_QueryId(IPin * iface, LPWSTR * Id);
HRESULT WINAPI IPinImpl_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt);
HRESULT WINAPI IPinImpl_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum);
HRESULT WINAPI IPinImpl_QueryInternalConnections(IPin * iface, IPin ** apPin, ULONG * cPin);
/* Input Pin */
HRESULT WINAPI InputPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv);
ULONG WINAPI InputPin_Release(IPin * iface);
HRESULT WINAPI InputPin_Connect(IPin * iface, IPin * pConnector, const AM_MEDIA_TYPE * pmt);
HRESULT WINAPI InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt);
HRESULT WINAPI InputPin_EndOfStream(IPin * iface);
HRESULT WINAPI InputPin_BeginFlush(IPin * iface);
HRESULT WINAPI InputPin_EndFlush(IPin * iface);
HRESULT WINAPI InputPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
/* Output Pin */
HRESULT WINAPI OutputPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv);
ULONG WINAPI OutputPin_Release(IPin * iface);
HRESULT WINAPI OutputPin_Connect(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt);
HRESULT WINAPI OutputPin_Disconnect(IPin * iface);
HRESULT WINAPI OutputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt);
HRESULT WINAPI OutputPin_EndOfStream(IPin * iface);
HRESULT WINAPI OutputPin_BeginFlush(IPin * iface);
HRESULT WINAPI OutputPin_EndFlush(IPin * iface);
HRESULT WINAPI OutputPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
HRESULT OutputPin_CommitAllocator(OutputPin * This);
HRESULT OutputPin_DecommitAllocator(OutputPin * This);
HRESULT OutputPin_GetDeliveryBuffer(OutputPin * This, IMediaSample ** ppSample, REFERENCE_TIME * tStart, REFERENCE_TIME * tStop, DWORD dwFlags);
HRESULT OutputPin_SendSample(OutputPin * This, IMediaSample * pSample);
HRESULT OutputPin_DeliverDisconnect(OutputPin * This);
/* Pull Pin */
HRESULT WINAPI PullPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt);
HRESULT WINAPI PullPin_Disconnect(IPin * iface);
HRESULT WINAPI PullPin_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv);
ULONG WINAPI PullPin_Release(IPin * iface);
HRESULT WINAPI PullPin_EndOfStream(IPin * iface);
HRESULT WINAPI PullPin_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt);
HRESULT WINAPI PullPin_BeginFlush(IPin * iface);
HRESULT WINAPI PullPin_EndFlush(IPin * iface);
HRESULT WINAPI PullPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
@ -202,3 +122,9 @@ HRESULT WINAPI PullPin_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE
HRESULT PullPin_StartProcessing(PullPin * This);
HRESULT PullPin_PauseProcessing(PullPin * This);
HRESULT PullPin_WaitForStateChange(PullPin * This, DWORD dwMilliseconds);
/* COM helpers */
static inline PullPin *impl_PullPin_from_IPin( IPin *iface )
{
return CONTAINING_RECORD(iface, PullPin, pin.IPin_iface);
}

View file

@ -2,9 +2,6 @@
*
* Copyright 2002 Lionel Ulmer
*
* This file contains the (internal) driver registration functions,
* driver enumeration APIs and DirectDraw creation functions.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@ -39,6 +36,7 @@
#include <objbase.h>
#include <oleauto.h>
#include <dshow.h>
#include <wine/strmbase.h>
#include <wine/list.h>
#define MEDIATIME_FROM_BYTES(x) ((LONGLONG)(x) * 10000000)
@ -46,60 +44,35 @@
#define BYTES_FROM_MEDIATIME(time) SEC_FROM_MEDIATIME(time)
#define MSEC_FROM_MEDIATIME(time) ((time) / 10000)
#define ICOM_THIS_MULTI(impl,field,iface) impl* const This=(impl*)((char*)(iface) - offsetof(impl,field))
HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj) DECLSPEC_HIDDEN;
HRESULT FilterGraphNoThread_create(IUnknown *pUnkOuter, LPVOID *ppObj) DECLSPEC_HIDDEN;
HRESULT FilterMapper2_create(IUnknown *pUnkOuter, LPVOID *ppObj) DECLSPEC_HIDDEN;
HRESULT FilterMapper_create(IUnknown *pUnkOuter, LPVOID *ppObj) DECLSPEC_HIDDEN;
HRESULT AsyncReader_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN;
HRESULT StdMemAllocator_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN;
HRESULT AVISplitter_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN;
HRESULT MPEGSplitter_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN;
HRESULT AVIDec_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN;
HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN;
HRESULT VideoRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN;
HRESULT NullRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN;
HRESULT VideoRendererDefault_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN;
HRESULT QUARTZ_CreateSystemClock(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN;
HRESULT ACMWrapper_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN;
HRESULT WAVEParser_create(IUnknown * pUnkOuter, LPVOID * ppv) DECLSPEC_HIDDEN;
HRESULT VMR9Impl_create(IUnknown *pUnkOuter, LPVOID *ppv) DECLSPEC_HIDDEN;
HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj);
HRESULT FilterGraphNoThread_create(IUnknown *pUnkOuter, LPVOID *ppObj);
HRESULT FilterMapper2_create(IUnknown *pUnkOuter, LPVOID *ppObj);
HRESULT FilterMapper_create(IUnknown *pUnkOuter, LPVOID *ppObj);
HRESULT AsyncReader_create(IUnknown * pUnkOuter, LPVOID * ppv);
HRESULT StdMemAllocator_create(IUnknown * pUnkOuter, LPVOID * ppv);
HRESULT AVISplitter_create(IUnknown * pUnkOuter, LPVOID * ppv);
HRESULT MPEGSplitter_create(IUnknown * pUnkOuter, LPVOID * ppv);
HRESULT AVIDec_create(IUnknown * pUnkOuter, LPVOID * ppv);
HRESULT DSoundRender_create(IUnknown * pUnkOuter, LPVOID * ppv);
HRESULT VideoRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv);
HRESULT NullRenderer_create(IUnknown * pUnkOuter, LPVOID * ppv);
HRESULT VideoRendererDefault_create(IUnknown * pUnkOuter, LPVOID * ppv);
HRESULT QUARTZ_CreateSystemClock(IUnknown * pUnkOuter, LPVOID * ppv);
HRESULT ACMWrapper_create(IUnknown * pUnkOuter, LPVOID * ppv);
HRESULT WAVEParser_create(IUnknown * pUnkOuter, LPVOID * ppv);
HRESULT SeekingPassThru_create(IUnknown *pUnkOuter, LPVOID *ppObj);
HRESULT EnumMonikerImpl_Create(IMoniker ** ppMoniker, ULONG nMonikerCount, IEnumMoniker ** ppEnum) DECLSPEC_HIDDEN;
HRESULT EnumMonikerImpl_Create(IMoniker ** ppMoniker, ULONG nMonikerCount, IEnumMoniker ** ppEnum);
HRESULT IEnumRegFiltersImpl_Construct(REGFILTER * pInRegFilters, const ULONG size, IEnumRegFilters ** ppEnum) DECLSPEC_HIDDEN;
HRESULT IEnumFiltersImpl_Construct(IGraphVersion * pVersionSource, IBaseFilter *** pppFilters, ULONG * pNumFilters, IEnumFilters ** ppEnum) DECLSPEC_HIDDEN;
typedef struct tagENUMEDIADETAILS
{
ULONG cMediaTypes;
AM_MEDIA_TYPE * pMediaTypes;
} ENUMMEDIADETAILS;
extern const char * qzdebugstr_guid(const GUID * id) DECLSPEC_HIDDEN;
extern void video_unregister_windowclass(void) DECLSPEC_HIDDEN;
typedef HRESULT (* FNOBTAINPIN)(IBaseFilter *iface, ULONG pos, IPin **pin, DWORD *lastsynctick);
HRESULT IEnumPinsImpl_Construct(IEnumPins ** ppEnum, FNOBTAINPIN receive_pin, IBaseFilter *base);
HRESULT IEnumMediaTypesImpl_Construct(const ENUMMEDIADETAILS * pDetails, IEnumMediaTypes ** ppEnum);
HRESULT IEnumRegFiltersImpl_Construct(REGFILTER * pInRegFilters, const ULONG size, IEnumRegFilters ** ppEnum);
HRESULT IEnumFiltersImpl_Construct(IBaseFilter ** ppFilters, ULONG nFilters, IEnumFilters ** ppEnum);
extern const char * qzdebugstr_guid(const GUID * id);
HRESULT CopyMediaType(AM_MEDIA_TYPE * pDest, const AM_MEDIA_TYPE *pSrc);
void FreeMediaType(AM_MEDIA_TYPE * pmt);
void DeleteMediaType(AM_MEDIA_TYPE * pmt);
BOOL CompareMediaTypes(const AM_MEDIA_TYPE * pmt1, const AM_MEDIA_TYPE * pmt2, BOOL bWildcards);
void dump_AM_MEDIA_TYPE(const AM_MEDIA_TYPE * pmt);
HRESULT updatehres( HRESULT original, HRESULT new );
void dump_AM_MEDIA_TYPE(const AM_MEDIA_TYPE * pmt) DECLSPEC_HIDDEN;
typedef struct StdMediaSample2
{
const IMediaSample2Vtbl * lpvtbl;
LONG ref;
AM_SAMPLE2_PROPERTIES props;
IMemAllocator * pParent;
struct list listentry;
LONGLONG tMediaStart;
LONGLONG tMediaEnd;
} StdMediaSample2;
HRESULT GetClassMediaFile(IAsyncReader * pReader, LPCOLESTR pszFileName, GUID * majorType, GUID * minorType, GUID * sourceFilter);
#endif /* __QUARTZ_PRIVATE_INCLUDED__ */

View file

@ -16,7 +16,144 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
/* just a wrapper for strmif.idl */
cpp_quote("#include <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; }

View file

@ -0,0 +1,269 @@
HKCR
{
NoRemove Interface
{
'{29840822-5B84-11D0-BD3B-00A0C911CE86}' = s 'ICreateDevEnum'
{
NumMethods = s 4
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{56A86891-0AD4-11CE-B03A-0020AF0BA770}' = s 'IPin'
{
NumMethods = s 18
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{56A86892-0AD4-11CE-B03A-0020AF0BA770}' = s 'IEnumPins'
{
NumMethods = s 7
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{89C31040-846B-11CE-97D3-00AA0055595A}' = s 'IEnumMediaTypes'
{
NumMethods = s 7
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{56A8689F-0AD4-11CE-B03A-0020AF0BA770}' = s 'IFilterGraph'
{
NumMethods = s 11
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{56A86893-0AD4-11CE-B03A-0020AF0BA770}' = s 'IEnumFilters'
{
NumMethods = s 7
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{56A86899-0AD4-11CE-B03A-0020AF0BA770}' = s 'IMediaFilter'
{
NumMethods = s 10
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{56A86895-0AD4-11CE-B03A-0020AF0BA770}' = s 'IBaseFilter'
{
NumMethods = s 15
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{56A86897-0AD4-11CE-B03A-0020AF0BA770}' = s 'IReferenceClock'
{
NumMethods = s 7
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{56A8689C-0AD4-11CE-B03A-0020AF0BA770}' = s 'IMemAllocator'
{
NumMethods = s 9
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{379A0CF0-C1DE-11D2-ABF5-00A0C905F375}' = s 'IMemAllocatorCallbackTemp'
{
NumMethods = s 11
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{92980B30-C1DE-11D2-ABF5-00A0C905F375}' = s 'IMemAllocatorNotifyCallbackTemp'
{
NumMethods = s 4
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{56A8689D-0AD4-11CE-B03A-0020AF0BA770}' = s 'IMemInputPin'
{
NumMethods = s 9
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{A3D8CEC0-7E5A-11CF-BBC5-00805F6CEF20}' = s 'IAMovieSetup'
{
NumMethods = s 5
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{36B73880-C2C8-11CF-8B46-00805F6CEF60}' = s 'IMediaSeeking'
{
NumMethods = s 20
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{56A868A4-0AD4-11CE-B03A-0020AF0BA770}' = s 'IEnumRegFilters'
{
NumMethods = s 7
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{56A868A3-0AD4-11CE-B03A-0020AF0BA770}' = s 'IFilterMapper'
{
NumMethods = s 11
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{B79BB0B0-33C1-11D1-ABE1-00A0C905F375}' = s 'IFilterMapper2'
{
NumMethods = s 7
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{B79BB0B1-33C1-11D1-ABE1-00A0C905F375}' = s 'IFilterMapper3'
{
NumMethods = s 8
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{56A868A5-0AD4-11CE-B03A-0020AF0BA770}' = s 'IQualityControl'
{
NumMethods = s 5
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{56A868A2-0AD4-11CE-B03A-0020AF0BA770}' = s 'IMediaEventSink'
{
NumMethods = s 4
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{56A868A6-0AD4-11CE-B03A-0020AF0BA770}' = s 'IFileSourceFilter'
{
NumMethods = s 5
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{A2104830-7C70-11CF-8BCE-00AA00A3F1A6}' = s 'IFileSinkFilter'
{
NumMethods = s 5
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{00855B90-CE1B-11D0-BD4F-00A0C911CE86}' = s 'IFileSinkFilter2'
{
NumMethods = s 7
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{56A868A9-0AD4-11CE-B03A-0020AF0BA770}' = s 'IGraphBuilder'
{
NumMethods = s 18
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{BF87B6E0-8C27-11D0-B3F0-00AA003761C5}' = s 'ICaptureGraphBuilder'
{
NumMethods = s 11
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{670D1D20-A068-11D0-B3F0-00AA003761C5}' = s 'IAMCopyCaptureFileProgress'
{
NumMethods = s 4
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{93E5A4E0-2D50-11D2-ABFA-00A0C9C6E38D}' = s 'ICaptureGraphBuilder2'
{
NumMethods = s 12
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{36B73882-C2C8-11CF-8B46-00805F6CEF60}' = s 'IFilterGraph2'
{
NumMethods = s 21
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{C6E13340-30AC-11D0-A18C-00A0C9118956}' = s 'IAMStreamConfig'
{
NumMethods = s 7
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{C6E13360-30AC-11D0-A18C-00A0C9118956}' = s 'IAMVideoProcAmp'
{
NumMethods = s 6
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{56A868AA-0AD4-11CE-B03A-0020AF0BA770}' = s 'IAsyncReader'
{
NumMethods = s 11
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{56A868AB-0AD4-11CE-B03A-0020AF0BA770}' = s 'IGraphVersion'
{
NumMethods = s 4
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{56A868AD-0AD4-11CE-B03A-0020AF0BA770}' = s 'IResourceConsumer'
{
NumMethods = s 5
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{56A868AC-0AD4-11CE-B03A-0020AF0BA770}' = s 'IResourceManager'
{
NumMethods = s 11
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
'{36B73883-C2C8-11CF-8B46-00805F6CEF60}' = s 'ISeekingPassThru'
{
NumMethods = s 4
ProxyStubClsid32 = s '{670D1D20-A068-11D0-B3F0-00AA003761C5}'
}
}
NoRemove CLSID
{
'{670D1D20-A068-11D0-B3F0-00AA003761C5}' = s 'PSFactoryBuffer'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
}
'{E436EBB3-524F-11CE-9F53-0020AF0BA770}' = s 'Filter Graph'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
}
'{E436EBB8-524F-11CE-9F53-0020AF0BA770}' = s 'Filter Graph no thread'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
}
'{E436EBB2-524F-11CE-9F53-0020AF0BA770}' = s 'Filter Mapper'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
}
'{CDA42200-BD88-11D0-BD4E-00A0C911CE86}' = s 'Filter Mapper2'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
}
'{E436EBB1-524F-11CE-9F53-0020AF0BA770}' = s 'System Clock'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
}
'{1E651CC0-B199-11D0-8212-00C04FC32C45}' = s 'Memory Allocator'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
}
'{060AF76C-68DD-11D0-8FC1-00C04FD9189D}' = s 'Seeking'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
}
'{E436EBB5-524F-11CE-9F53-0020AF0BA770}' = s 'File Source Filter'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
}
'{1B544C20-FD0B-11CE-8C63-00AA0044B51E}' = s 'AVI Splitter'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
}
'{336475D0-942A-11CE-A870-00AA002FEAB5}' = s 'MPEG-I Stream Splitter'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
}
'{CF49D4E0-1115-11CE-B03A-0020AF0BA770}' = s 'AVI Decompressor'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
}
'{79376820-07D0-11CF-A24D-0020AFD79767}' = s 'DirectSound Audio Renderer'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
}
'{E30629D1-27E5-11CE-875D-00608CB78066}' = s 'Wave Audio Renderer'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
}
'{C1F400A4-3F08-11D3-9F0B-006008039E37}' = s 'Null Renderer'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
}
'{70E102B0-5556-11CE-97C0-00AA0055595A}' = s 'Video Renderer'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
}
'{6BC1CFFA-8FC1-4261-AC22-CFB4CC38DB50}' = s 'Default Video Renderer'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
}
'{6A08CF80-0E18-11CF-A24D-0020AFD79767}' = s 'ACM wrapper'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
}
'{D51BD5A1-7548-11CF-A520-0080C77EF58A}' = s 'Wave Parser'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
}
'{51B4ABF3-748F-4E3B-A276-C828330E926A}' = s 'Video Mixing Renderer 9'
{
InprocServer32 = s '%MODULE%' { val ThreadingModel = s 'Both' }
}
}
}

View file

@ -129,43 +129,43 @@ static HRESULT unregister_filters(struct regsvr_filter const *list);
/***********************************************************************
* static string constants
*/
static WCHAR const interface_keyname[10] = {
static const WCHAR interface_keyname[] = {
'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
static WCHAR const base_ifa_keyname[14] = {
static const WCHAR base_ifa_keyname[] = {
'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
'e', 0 };
static WCHAR const num_methods_keyname[11] = {
static const WCHAR num_methods_keyname[] = {
'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
static WCHAR const ps_clsid_keyname[15] = {
static const WCHAR ps_clsid_keyname[] = {
'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
'i', 'd', 0 };
static WCHAR const ps_clsid32_keyname[17] = {
static const WCHAR ps_clsid32_keyname[] = {
'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
'i', 'd', '3', '2', 0 };
static WCHAR const clsid_keyname[6] = {
static const WCHAR clsid_keyname[] = {
'C', 'L', 'S', 'I', 'D', 0 };
static WCHAR const curver_keyname[7] = {
static const WCHAR curver_keyname[] = {
'C', 'u', 'r', 'V', 'e', 'r', 0 };
static WCHAR const ips_keyname[13] = {
static const WCHAR ips_keyname[] = {
'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
0 };
static WCHAR const ips32_keyname[15] = {
static const WCHAR ips32_keyname[] = {
'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
'3', '2', 0 };
static WCHAR const progid_keyname[7] = {
static const WCHAR progid_keyname[] = {
'P', 'r', 'o', 'g', 'I', 'D', 0 };
static WCHAR const viprogid_keyname[25] = {
static const WCHAR viprogid_keyname[] = {
'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
0 };
static char const tmodel_valuename[] = "ThreadingModel";
static WCHAR const mediatype_name[11] = {
static const char tmodel_valuename[] = "ThreadingModel";
static const WCHAR mediatype_name[] = {
'M', 'e', 'd', 'i', 'a', ' ', 'T', 'y', 'p', 'e', 0 };
static WCHAR const subtype_valuename[8] = {
static const WCHAR subtype_valuename[] = {
'S', 'u', 'b', 't', 'y', 'p', 'e', 0 };
static WCHAR const sourcefilter_valuename[14] = {
static const WCHAR sourcefilter_valuename[] = {
'S', 'o', 'u', 'r', 'c', 'e', ' ', 'F', 'i', 'l', 't', 'e', 'r', 0 };
static WCHAR const extensions_keyname[11] = {
static const WCHAR extensions_keyname[] = {
'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', 0 };
/***********************************************************************
@ -214,7 +214,7 @@ static HRESULT register_interfaces(struct regsvr_interface const *list)
}
if (0 <= list->num_methods) {
static WCHAR const fmt[3] = { '%', 'd', 0 };
static const WCHAR fmt[] = { '%', 'd', 0 };
HKEY key;
res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
@ -595,8 +595,8 @@ static HRESULT register_filters(struct regsvr_filter const *list)
for (i = 0; list->pins[i].flags != 0xFFFFFFFF; i++) ;
rf2.dwVersion = 2;
rf2.dwMerit = list->merit;
rf2.u.s1.cPins2 = i;
rf2.u.s1.rgPins2 = prfp2 = CoTaskMemAlloc(i*sizeof(REGFILTERPINS2));
rf2.u.s2.cPins2 = i;
rf2.u.s2.rgPins2 = prfp2 = CoTaskMemAlloc(i*sizeof(REGFILTERPINS2));
if (!prfp2) {
hr = E_OUTOFMEMORY;
break;
@ -783,121 +783,10 @@ error_close_progid_key:
return res;
}
static GUID const CLSID_PSFactoryBuffer = {
0x92a3a302, 0xda7c, 0x4a1f, {0xba,0x7e,0x18,0x02,0xbb,0x5d,0x2d,0x02} };
/***********************************************************************
* coclass list
*/
static struct regsvr_coclass const coclass_list[] = {
{ &CLSID_FilterGraph,
"Filter Graph",
NULL,
"quartz.dll",
"Both"
},
{ &CLSID_FilterGraphNoThread,
"Filter Graph",
NULL,
"quartz.dll",
"Both"
},
{ &CLSID_FilterMapper,
"Filter Mapper",
NULL,
"quartz.dll",
"Both"
},
{ &CLSID_FilterMapper2,
"Filter Mapper2",
NULL,
"quartz.dll",
"Both"
},
{ &CLSID_SystemClock,
"System Clock",
NULL,
"quartz.dll",
"Both"
},
{ &CLSID_MemoryAllocator,
"Memory Allocator",
NULL,
"quartz.dll",
"Both"
},
{ &CLSID_SeekingPassThru,
"Seeking",
NULL,
"quartz.dll",
"Both"
},
{ &CLSID_AsyncReader,
"File Source Filter",
NULL,
"quartz.dll",
"Both"
},
{ &CLSID_AviSplitter,
"AVI Splitter",
NULL,
"quartz.dll",
"Both"
},
{ &CLSID_MPEG1Splitter,
"MPEG-I Stream Splitter",
NULL,
"quartz.dll",
"Both"
},
{ &CLSID_AVIDec,
"AVI Decompressor",
NULL,
"quartz.dll",
"Both"
},
{ &CLSID_DSoundRender,
"DirectSound Audio Renderer",
NULL,
"quartz.dll",
"Both"
},
{ &CLSID_AudioRender,
"Wave Audio Renderer",
NULL,
"quartz.dll",
"Both"
},
{ &CLSID_NullRenderer,
"Null Renderer",
NULL,
"quartz.dll",
"Both"
},
{ &CLSID_VideoRenderer,
"Video Renderer",
NULL,
"quartz.dll",
"Both"
},
{ &CLSID_VideoRendererDefault,
"Default Video Renderer",
NULL,
"quartz.dll",
"Both"
},
{ &CLSID_ACMWrapper,
"ACM wrapper",
NULL,
"quartz.dll",
"Both"
},
{ &CLSID_WAVEParser,
"Wave Parser",
NULL,
"quartz.dll",
"Both"
},
{ NULL } /* list terminator */
};
@ -997,7 +886,7 @@ static struct regsvr_filter const filter_list[] = {
{ &CLSID_AviSplitter,
&CLSID_LegacyAmFilterCategory,
{'A','V','I',' ','S','p','l','i','t','t','e','r',0},
0x600000,
0x5ffff0,
{ { 0,
{ { &MEDIATYPE_Stream, &MEDIASUBTYPE_Avi },
{ NULL }
@ -1014,7 +903,7 @@ static struct regsvr_filter const filter_list[] = {
{ &CLSID_MPEG1Splitter,
&CLSID_LegacyAmFilterCategory,
{'M','P','E','G','-','I',' ','S','t','r','e','a','m',' ','S','p','l','i','t','t','e','r',0},
0x600000,
0x5ffff0,
{ { 0,
{ { &MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1Audio },
{ &MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1Video },
@ -1074,6 +963,18 @@ static struct regsvr_filter const filter_list[] = {
{ 0xFFFFFFFF },
}
},
{ &CLSID_VideoMixingRenderer9,
&CLSID_LegacyAmFilterCategory,
{'V','i','d','e','o',' ','M','i','x','i','n','g',' ','R','e','n','d','e','r','e','r',' ','9',0},
0x200000,
{ { REG_PINFLAG_B_RENDERER,
{ { &MEDIATYPE_Video, &GUID_NULL },
{ NULL }
},
},
{ 0xFFFFFFFF },
}
},
{ &CLSID_DSoundRender,
&CLSID_LegacyAmFilterCategory,
{'A','u','d','i','o',' ','R','e','n','d','e','r','e','r',0},
@ -1103,7 +1004,7 @@ static struct regsvr_filter const filter_list[] = {
{ &CLSID_AVIDec,
&CLSID_LegacyAmFilterCategory,
{'A','V','I',' ','D','e','c','o','m','p','r','e','s','s','o','r',0},
0x600000,
0x5ffff0,
{ { 0,
{ { &MEDIATYPE_Video, &GUID_NULL },
{ NULL }
@ -1132,7 +1033,7 @@ static struct regsvr_filter const filter_list[] = {
{ &CLSID_ACMWrapper,
&CLSID_LegacyAmFilterCategory,
{'A','C','M',' ','W','r','a','p','p','e','r',0},
0x600000,
0x5ffff0,
{ { 0,
{ { &MEDIATYPE_Audio, &GUID_NULL },
{ NULL }

View file

@ -37,7 +37,7 @@ struct SystemClockAdviseEntry {
};
typedef struct SystemClockImpl {
const IReferenceClockVtbl *lpVtbl;
IReferenceClock IReferenceClock_iface;
LONG ref;
/** IReferenceClock */
@ -52,6 +52,11 @@ typedef struct SystemClockImpl {
SystemClockAdviseEntry* pPeriodicAdvise;
} SystemClockImpl;
static inline SystemClockImpl *impl_from_IReferenceClock(IReferenceClock *iface)
{
return CONTAINING_RECORD(iface, SystemClockImpl, IReferenceClock_iface);
}
static void QUARTZ_RemoveAviseEntryFromQueue(SystemClockImpl* This, SystemClockAdviseEntry* pEntry) {
if (pEntry->prev) pEntry->prev->next = pEntry->next;
@ -104,19 +109,22 @@ static DWORD WINAPI SystemClockAdviseThread(LPVOID lpParam) {
EnterCriticalSection(&This->safe);
/*timeOut = IReferenceClock_OnTimerUpdated(This); */
hr = IReferenceClock_GetTime((IReferenceClock*) This, &curTime);
hr = IReferenceClock_GetTime(&This->IReferenceClock_iface, &curTime);
if (FAILED(hr)) {
timeOut = INFINITE;
goto outrefresh;
}
/** First SingleShots Advice: sorted list */
for (it = This->pSingleShotAdvise; NULL != it && (it->rtBaseTime + it->rtIntervalTime) <= curTime; it = it->next) {
it = This->pSingleShotAdvise;
while ((NULL != it) && (it->rtBaseTime + it->rtIntervalTime) <= curTime) {
SystemClockAdviseEntry* nextit = it->next;
/** send event ... */
SetEvent(it->hEvent);
/** ... and Release it */
QUARTZ_RemoveAviseEntryFromQueue(This, it);
CoTaskMemFree(it);
it = nextit;
}
if (NULL != it) timeOut = (DWORD) ((it->rtBaseTime + it->rtIntervalTime) - curTime) / (REFERENCE_TIME)10000;
@ -137,11 +145,11 @@ static DWORD WINAPI SystemClockAdviseThread(LPVOID lpParam) {
outrefresh:
LeaveCriticalSection(&This->safe);
while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) {
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) {
/** if hwnd we suppose that is a windows event ... */
if (NULL != msg.hwnd) {
TranslateMessage(&msg);
DispatchMessageA(&msg);
DispatchMessageW(&msg);
} else {
switch (msg.message) {
case WM_QUIT:
@ -178,7 +186,7 @@ static BOOL SystemClockPostMessageToAdviseThread(SystemClockImpl* This, UINT iMs
SetThreadPriority(This->adviseThread, THREAD_PRIORITY_TIME_CRITICAL);
This->adviseThreadActive = TRUE;
while(1) {
res = PostThreadMessageA(This->adviseThreadId, iMsg, 0, 0);
res = PostThreadMessageW(This->adviseThreadId, iMsg, 0, 0);
/* Let the thread creates its message queue (with MsgWaitForMultipleObjects call) by yielding and retrying */
if (!res && (GetLastError() == ERROR_INVALID_THREAD_ID))
Sleep(0);
@ -187,11 +195,11 @@ static BOOL SystemClockPostMessageToAdviseThread(SystemClockImpl* This, UINT iMs
}
return res;
}
return PostThreadMessageA(This->adviseThreadId, iMsg, 0, 0);
return PostThreadMessageW(This->adviseThreadId, iMsg, 0, 0);
}
static ULONG WINAPI SystemClockImpl_AddRef(IReferenceClock* iface) {
SystemClockImpl *This = (SystemClockImpl *)iface;
SystemClockImpl *This = impl_from_IReferenceClock(iface);
ULONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p): AddRef from %d\n", This, ref - 1);
@ -200,7 +208,7 @@ static ULONG WINAPI SystemClockImpl_AddRef(IReferenceClock* iface) {
}
static HRESULT WINAPI SystemClockImpl_QueryInterface(IReferenceClock* iface, REFIID riid, void** ppobj) {
SystemClockImpl *This = (SystemClockImpl *)iface;
SystemClockImpl *This = impl_from_IReferenceClock(iface);
TRACE("(%p, %s,%p)\n", This, debugstr_guid(riid), ppobj);
if (IsEqualIID (riid, &IID_IUnknown) ||
@ -216,7 +224,7 @@ static HRESULT WINAPI SystemClockImpl_QueryInterface(IReferenceClock* iface, REF
}
static ULONG WINAPI SystemClockImpl_Release(IReferenceClock* iface) {
SystemClockImpl *This = (SystemClockImpl *)iface;
SystemClockImpl *This = impl_from_IReferenceClock(iface);
ULONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p): ReleaseRef to %d\n", This, ref);
if (ref == 0) {
@ -232,7 +240,7 @@ static ULONG WINAPI SystemClockImpl_Release(IReferenceClock* iface) {
}
static HRESULT WINAPI SystemClockImpl_GetTime(IReferenceClock* iface, REFERENCE_TIME* pTime) {
SystemClockImpl *This = (SystemClockImpl *)iface;
SystemClockImpl *This = impl_from_IReferenceClock(iface);
DWORD curTimeTickCount;
HRESULT hr = S_OK;
@ -254,7 +262,7 @@ static HRESULT WINAPI SystemClockImpl_GetTime(IReferenceClock* iface, REFERENCE_
}
static HRESULT WINAPI SystemClockImpl_AdviseTime(IReferenceClock* iface, REFERENCE_TIME rtBaseTime, REFERENCE_TIME rtStreamTime, HEVENT hEvent, DWORD_PTR* pdwAdviseCookie) {
SystemClockImpl *This = (SystemClockImpl *)iface;
SystemClockImpl *This = impl_from_IReferenceClock(iface);
SystemClockAdviseEntry* pEntry = NULL;
TRACE("(%p, 0x%s, 0x%s, %ld, %p)\n", This, wine_dbgstr_longlong(rtBaseTime),
@ -290,7 +298,7 @@ static HRESULT WINAPI SystemClockImpl_AdviseTime(IReferenceClock* iface, REFEREN
}
static HRESULT WINAPI SystemClockImpl_AdvisePeriodic(IReferenceClock* iface, REFERENCE_TIME rtStartTime, REFERENCE_TIME rtPeriodTime, HSEMAPHORE hSemaphore, DWORD_PTR* pdwAdviseCookie) {
SystemClockImpl *This = (SystemClockImpl *)iface;
SystemClockImpl *This = impl_from_IReferenceClock(iface);
SystemClockAdviseEntry* pEntry = NULL;
TRACE("(%p, 0x%s, 0x%s, %ld, %p)\n", This, wine_dbgstr_longlong(rtStartTime),
@ -326,7 +334,7 @@ static HRESULT WINAPI SystemClockImpl_AdvisePeriodic(IReferenceClock* iface, REF
}
static HRESULT WINAPI SystemClockImpl_Unadvise(IReferenceClock* iface, DWORD_PTR dwAdviseCookie) {
SystemClockImpl *This = (SystemClockImpl *)iface;
SystemClockImpl *This = impl_from_IReferenceClock(iface);
SystemClockAdviseEntry* pEntry = NULL;
SystemClockAdviseEntry* it = NULL;
HRESULT ret = S_OK;
@ -377,12 +385,12 @@ HRESULT QUARTZ_CreateSystemClock(IUnknown * pUnkOuter, LPVOID * ppv) {
}
ZeroMemory(obj, sizeof(SystemClockImpl));
obj->lpVtbl = &SystemClock_Vtbl;
obj->IReferenceClock_iface.lpVtbl = &SystemClock_Vtbl;
obj->ref = 0; /* will be inited by QueryInterface */
obj->lastTimeTickCount = GetTickCount();
InitializeCriticalSection(&obj->safe);
obj->safe.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SystemClockImpl.safe");
return SystemClockImpl_QueryInterface((IReferenceClock*) obj, &IID_IReferenceClock, ppv);
return SystemClockImpl_QueryInterface(&obj->IReferenceClock_iface, &IID_IReferenceClock, ppv);
}

View file

@ -1,651 +0,0 @@
/*
* Transform Filter (Base for decoders, etc...)
*
* Copyright 2005 Christian Costa
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <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
};

View file

@ -1,54 +0,0 @@
/*
* Transform Filter declarations
*
* Copyright 2005 Christian Costa
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "control_private.h"
typedef struct TransformFilterImpl TransformFilterImpl;
typedef struct TransformFuncsTable {
HRESULT (*pfnProcessBegin) (TransformFilterImpl *This);
HRESULT (*pfnProcessSampleData) (InputPin *pin, IMediaSample *pSample);
HRESULT (*pfnProcessEnd) (TransformFilterImpl *This);
HRESULT (*pfnQueryConnect) (TransformFilterImpl *This, const AM_MEDIA_TYPE * pmt);
HRESULT (*pfnConnectInput) (InputPin *pin, const AM_MEDIA_TYPE * pmt);
HRESULT (*pfnCleanup) (InputPin *pin);
} TransformFuncsTable;
struct TransformFilterImpl
{
const IBaseFilterVtbl * lpVtbl;
LONG refCount;
CRITICAL_SECTION csFilter;
FILTER_STATE state;
REFERENCE_TIME rtStreamStart;
IReferenceClock * pClock;
FILTER_INFO filterInfo;
CLSID clsid;
struct MediaSeekingImpl mediaSeeking;
IPin **ppPins;
ULONG npins;
AM_MEDIA_TYPE pmt;
const TransformFuncsTable * pFuncsTable;
};
HRESULT TransformFilter_Create(TransformFilterImpl*, const CLSID*, const TransformFuncsTable* pFuncsTable, CHANGEPROC stop, CHANGEPROC current, CHANGEPROC rate);

View file

@ -16,12 +16,17 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define WINE_OLESELFREGISTER
#define WINE_FILEDESCRIPTION_STR "Wine Quartz dll"
#define WINE_FILENAME_STR "quartz.dll"
#define WINE_FILEVERSION 6,5,1,902
#define WINE_FILEVERSION_STR "6.5.1.902"
#define WINE_PRODUCTVERSION 6,5,1,902
#define WINE_PRODUCTVERSION_STR "6.5"
#define WINE_EXTRAVALUES VALUE "OLESelfRegister",""
#include "wine/wine_common_ver.rc"
1 TYPELIB control_tlb.tlb
1 WINE_REGISTRY control_tlb.rgs
2 WINE_REGISTRY quartz_strmif.rgs

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -19,7 +19,6 @@
*/
#include "quartz_private.h"
#include "control_private.h"
#include "pin.h"
//#include "uuids.h"
@ -49,6 +48,16 @@ typedef struct WAVEParserImpl
DWORD dwLength;
} WAVEParserImpl;
static inline WAVEParserImpl *impl_from_IMediaSeeking( IMediaSeeking *iface )
{
return CONTAINING_RECORD(iface, WAVEParserImpl, Parser.sourceSeeking.IMediaSeeking_iface);
}
static inline WAVEParserImpl *impl_from_IBaseFilter( IBaseFilter *iface )
{
return CONTAINING_RECORD(iface, WAVEParserImpl, Parser.filter.IBaseFilter_iface);
}
static LONGLONG bytepos_to_duration(WAVEParserImpl *This, LONGLONG bytepos)
{
LONGLONG duration = BYTES_FROM_MEDIATIME(bytepos - This->StartOfFile);
@ -94,7 +103,7 @@ static HRESULT WAVEParser_Sample(LPVOID iface, IMediaSample * pSample, DWORD_PTR
return S_OK;
}
pOutputPin = (Parser_OutputPin *)This->Parser.ppPins[1];
pOutputPin = unsafe_impl_Parser_OutputPin_from_IPin(This->Parser.ppPins[1]);
if (SUCCEEDED(hr))
hr = IMemAllocator_GetBuffer(pin->pAlloc, &newsample, NULL, NULL, 0);
@ -132,7 +141,7 @@ static HRESULT WAVEParser_Sample(LPVOID iface, IMediaSample * pSample, DWORD_PTR
IMediaSample_SetTime(pSample, &tAviStart, &tAviStop);
hr = OutputPin_SendSample(&pOutputPin->pin, pSample);
hr = BaseOutputPinImpl_Deliver(&pOutputPin->pin, pSample);
if (hr != S_OK && hr != S_FALSE && hr != VFW_E_WRONG_STATE)
ERR("Error sending sample (%x)\n", hr);
else if (hr != S_OK)
@ -140,7 +149,7 @@ static HRESULT WAVEParser_Sample(LPVOID iface, IMediaSample * pSample, DWORD_PTR
This->Parser.pInputPin->rtCurrent = tStart;
}
if (tStop >= This->EndOfFile || (bytepos_to_duration(This, tStop) >= This->Parser.mediaSeeking.llStop) || hr == VFW_E_NOT_CONNECTED)
if (tStop >= This->EndOfFile || (bytepos_to_duration(This, tStop) >= This->Parser.sourceSeeking.llStop) || hr == VFW_E_NOT_CONNECTED)
{
unsigned int i;
@ -184,14 +193,14 @@ static HRESULT WAVEParser_QueryAccept(LPVOID iface, const AM_MEDIA_TYPE * pmt)
return S_FALSE;
}
static HRESULT WAVEParserImpl_seek(IBaseFilter *iface)
static HRESULT WINAPI WAVEParserImpl_seek(IMediaSeeking *iface)
{
WAVEParserImpl *This = (WAVEParserImpl *)iface;
WAVEParserImpl *This = impl_from_IMediaSeeking(iface);
PullPin *pPin = This->Parser.pInputPin;
IPin *victim = NULL;
LONGLONG newpos, curpos, endpos, bytepos;
newpos = This->Parser.mediaSeeking.llCurrent;
newpos = This->Parser.sourceSeeking.llCurrent;
curpos = bytepos_to_duration(This, pPin->rtCurrent);
endpos = bytepos_to_duration(This, This->EndOfFile);
bytepos = duration_to_bytepos(This, newpos);
@ -211,10 +220,10 @@ static HRESULT WAVEParserImpl_seek(IBaseFilter *iface)
TRACE("Moving sound to %08u bytes!\n", (DWORD)BYTES_FROM_MEDIATIME(bytepos));
EnterCriticalSection(&pPin->thread_lock);
IPin_BeginFlush((IPin *)pPin);
IPin_BeginFlush(&pPin->pin.IPin_iface);
/* Make sure this is done while stopped, BeginFlush takes care of this */
EnterCriticalSection(&This->Parser.csFilter);
EnterCriticalSection(&This->Parser.filter.csFilter);
IPin_ConnectedTo(This->Parser.ppPins[1], &victim);
if (victim)
{
@ -223,11 +232,11 @@ static HRESULT WAVEParserImpl_seek(IBaseFilter *iface)
}
pPin->rtStart = pPin->rtCurrent = bytepos;
((Parser_OutputPin *)This->Parser.ppPins[1])->dwSamplesProcessed = 0;
LeaveCriticalSection(&This->Parser.csFilter);
unsafe_impl_Parser_OutputPin_from_IPin(This->Parser.ppPins[1])->dwSamplesProcessed = 0;
LeaveCriticalSection(&This->Parser.filter.csFilter);
TRACE("Done flushing\n");
IPin_EndFlush((IPin *)pPin);
IPin_EndFlush(&pPin->pin.IPin_iface);
LeaveCriticalSection(&pPin->thread_lock);
return S_OK;
@ -235,18 +244,18 @@ static HRESULT WAVEParserImpl_seek(IBaseFilter *iface)
static HRESULT WAVEParser_InputPin_PreConnect(IPin * iface, IPin * pConnectPin, ALLOCATOR_PROPERTIES *props)
{
PullPin *This = (PullPin *)iface;
PullPin *This = impl_PullPin_from_IPin(iface);
HRESULT hr;
RIFFLIST list;
RIFFCHUNK chunk;
LONGLONG pos = 0; /* in bytes */
PIN_INFO piOutput;
AM_MEDIA_TYPE amt;
WAVEParserImpl * pWAVEParser = (WAVEParserImpl *)This->pin.pinInfo.pFilter;
WAVEParserImpl * pWAVEParser = impl_from_IBaseFilter(This->pin.pinInfo.pFilter);
LONGLONG length, avail;
piOutput.dir = PINDIR_OUTPUT;
piOutput.pFilter = (IBaseFilter *)This;
piOutput.pFilter = &pWAVEParser->Parser.filter.IBaseFilter_iface;
lstrcpynW(piOutput.achName, wcsOutputPinName, sizeof(piOutput.achName) / sizeof(piOutput.achName[0]));
hr = IAsyncReader_SyncRead(This->pReader, pos, sizeof(list), (BYTE *)&list);
@ -319,9 +328,9 @@ static HRESULT WAVEParser_InputPin_PreConnect(IPin * iface, IPin * pConnectPin,
hr = Parser_AddPin(&(pWAVEParser->Parser), &piOutput, props, &amt);
CoTaskMemFree(amt.pbFormat);
pWAVEParser->Parser.mediaSeeking.llCurrent = 0;
pWAVEParser->Parser.mediaSeeking.llStop = pWAVEParser->Parser.mediaSeeking.llDuration = bytepos_to_duration(pWAVEParser, pWAVEParser->EndOfFile);
TRACE("Duration: %u seconds\n", (DWORD)(pWAVEParser->Parser.mediaSeeking.llDuration / (LONGLONG)10000000));
pWAVEParser->Parser.sourceSeeking.llCurrent = 0;
pWAVEParser->Parser.sourceSeeking.llStop = pWAVEParser->Parser.sourceSeeking.llDuration = bytepos_to_duration(pWAVEParser, pWAVEParser->EndOfFile);
TRACE("Duration: %u seconds\n", (DWORD)(pWAVEParser->Parser.sourceSeeking.llDuration / (LONGLONG)10000000));
This->rtStop = pWAVEParser->EndOfFile;
This->rtStart = pWAVEParser->StartOfFile;
@ -362,7 +371,7 @@ static HRESULT WAVEParser_first_request(LPVOID iface)
LONGLONG rtSampleStart = pin->rtNext;
/* Add 4 for the next header, which should hopefully work */
LONGLONG rtSampleStop = rtSampleStart + MEDIATIME_FROM_BYTES(IMediaSample_GetSize(sample));
Parser_OutputPin *outpin = (Parser_OutputPin *)This->Parser.ppPins[1];
Parser_OutputPin *outpin = unsafe_impl_Parser_OutputPin_from_IPin(This->Parser.ppPins[1]);
if (rtSampleStop > pin->rtStop)
rtSampleStop = MEDIATIME_FROM_BYTES(ALIGNUP(BYTES_FROM_MEDIATIME(pin->rtStop), pin->cbAlign));

View file

@ -19,7 +19,6 @@ list(APPEND SOURCE
mmstream.idl
qedit.idl
regbag.idl
strmif.idl
tvratings.idl
vidcap.idl
videoacc.idl

View file

@ -45,6 +45,7 @@ interface IAMVfwCompressDialogs;
interface IAMVideoCompression;
interface IAMVideoDecimationProperties;
interface IAMVideoProcAmp;
interface IAMGraphBuilderCallback;
interface ICaptureGraphBuilder;
interface ICaptureGraphBuilder2;
interface IConfigAviMux;
@ -235,14 +236,14 @@ typedef struct
{
ULONG cPins;
[size_is(cPins)] const REGFILTERPINS *rgPins;
} DUMMYSTRUCTNAME;
} DUMMYSTRUCTNAME1;
[case(2)]
struct
{
ULONG cPins2;
[size_is(cPins2)] const REGFILTERPINS2 *rgPins2;
} DUMMYSTRUCTNAME1;
} DUMMYSTRUCTNAME2;
[default]
;
@ -1070,6 +1071,21 @@ interface IAMFilterMiscFlags : IUnknown
ULONG GetMiscFlags();
};
[
local,
object,
uuid(4995f511-9ddb-4f12-bd3b-f04611807b79),
pointer_default(unique)
]
interface IAMGraphBuilderCallback : IUnknown
{
HRESULT SelectedFilter(
[in] IMoniker *pMon);
HRESULT CreatedFilter(
[in] IBaseFilter *pFil);
};
[
local,
object,

View file

@ -19,228 +19,230 @@
import "oaidl.idl";
interface IMediaControl;
interface IBasicAudio;
interface IBasicVideo;
interface IVideoWindow;
interface IMediaEvent;
interface IMediaEventEx;
interface IMediaPosition;
typedef LONG OAFilterState;
typedef LONG_PTR OAHWND;
typedef LONG_PTR OAEVENT;
cpp_quote("#ifndef REFTIME_DEFINED")
cpp_quote("#define REFTIME_DEFINED")
typedef DOUBLE REFTIME;
cpp_quote("#endif")
/*****************************************************************************
* IMediaControl interface
*/
[
object,
uuid(56a868b1-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
version(1.0),
uuid(56a868b0-0ad4-11ce-b03a-0020af0ba770)
]
interface IMediaControl : IDispatch
library QuartzTypeLib
{
HRESULT Run();
HRESULT Pause();
HRESULT Stop();
HRESULT GetState( [in] LONG msTimeout, [out] OAFilterState *pfs );
HRESULT RenderFile( [in] BSTR strFilename );
HRESULT AddSourceFilter( [in] BSTR strFilename, [out] IDispatch **ppUnk );
[propget] HRESULT FilterCollection( [out] IDispatch **ppUnk );
[propget] HRESULT RegFilterCollection( [out] IDispatch **ppUnk );
HRESULT StopWhenReady();
}
importlib("stdole2.tlb");
typedef LONG OAFilterState;
typedef LONG_PTR OAHWND;
typedef LONG_PTR OAEVENT;
cpp_quote("#ifndef REFTIME_DEFINED")
cpp_quote("#define REFTIME_DEFINED")
typedef DOUBLE REFTIME;
cpp_quote("#endif")
/***************************************************************************
* IMediaControl interface
*/
[
object,
uuid(56a868b1-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IMediaControl : IDispatch
{
HRESULT Run();
HRESULT Pause();
HRESULT Stop();
HRESULT GetState( [in] LONG msTimeout, [out] OAFilterState *pfs );
HRESULT RenderFile( [in] BSTR strFilename );
HRESULT AddSourceFilter( [in] BSTR strFilename, [out] IDispatch **ppUnk );
[propget] HRESULT FilterCollection( [out] IDispatch **ppUnk );
[propget] HRESULT RegFilterCollection( [out] IDispatch **ppUnk );
HRESULT StopWhenReady();
}
/*****************************************************************************
* IBasicAudio interface
*/
[
object,
uuid(56a868b3-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IBasicAudio : IDispatch
{
[propput] HRESULT Volume( [in] LONG lVolume );
[propget] HRESULT Volume( [out] LONG *plVolume );
[propput] HRESULT Balance( [in] LONG lBalance );
[propget] HRESULT Balance( [out] LONG *plBalance );
}
/***************************************************************************
* IBasicAudio interface
*/
[
object,
uuid(56a868b3-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IBasicAudio : IDispatch
{
[propput] HRESULT Volume( [in] LONG lVolume );
[propget] HRESULT Volume( [out] LONG *plVolume );
[propput] HRESULT Balance( [in] LONG lBalance );
[propget] HRESULT Balance( [out] LONG *plBalance );
}
/*****************************************************************************
* IVideoWindow interface
*/
[
object,
uuid(56a868b4-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IVideoWindow : IDispatch
{
[propput] HRESULT Caption( [in] BSTR strCaption );
[propget] HRESULT Caption( [out] BSTR *strCaption );
[propput] HRESULT WindowStyle( [in] LONG WindowStyle );
[propget] HRESULT WindowStyle( [out] LONG *WindowStyle );
[propput] HRESULT WindowStyleEx( [in] LONG WindowStyleEx );
[propget] HRESULT WindowStyleEx( [out] LONG *WindowStyleEx );
[propput] HRESULT AutoShow( [in] LONG AutoShow );
[propget] HRESULT AutoShow( [out] LONG *AutoShow );
[propput] HRESULT WindowState( [in] LONG WindowState );
[propget] HRESULT WindowState( [out] LONG *WindowState );
[propput] HRESULT BackgroundPalette( [in] LONG BackgroundPalette );
[propget] HRESULT BackgroundPalette( [out] LONG *pBackgroundPalette );
[propput] HRESULT Visible( [in] LONG Visible );
[propget] HRESULT Visible( [out] LONG *pVisible );
[propput] HRESULT Left( [in] LONG Left );
[propget] HRESULT Left( [out] LONG *pLeft );
[propput] HRESULT Width( [in] LONG Width );
[propget] HRESULT Width( [out] LONG *pWidth );
[propput] HRESULT Top( [in] LONG Top );
[propget] HRESULT Top( [out] LONG *pTop );
[propput] HRESULT Height( [in] LONG Height );
[propget] HRESULT Height( [out] LONG *pHeight );
[propput] HRESULT Owner( [in] OAHWND Owner );
[propget] HRESULT Owner( [out] OAHWND *Owner );
[propput] HRESULT MessageDrain( [in] OAHWND Drain );
[propget] HRESULT MessageDrain( [out] OAHWND *Drain );
[propget] HRESULT BorderColor( [out] LONG *Color );
[propput] HRESULT BorderColor( [in] LONG Color );
[propget] HRESULT FullScreenMode( [out] LONG *FullScreenMode );
[propput] HRESULT FullScreenMode( [in] LONG FullScreenMode );
HRESULT SetWindowForeground( [in] LONG Focus );
HRESULT NotifyOwnerMessage( [in] OAHWND hwnd, [in] LONG uMsg, [in] LONG_PTR wParam, [in] LONG_PTR lParam );
HRESULT SetWindowPosition( [in] LONG Left, [in] LONG Top, [in] LONG Width, [in] LONG Height );
HRESULT GetWindowPosition( [out] LONG *pLeft, [out] LONG *pTop, [out] LONG *pWidth, [out] LONG *pHeight );
HRESULT GetMinIdealImageSize( [out] LONG *pWidth, [out] LONG *pHeight );
HRESULT GetMaxIdealImageSize( [out] LONG *pWidth, [out] LONG *pHeight );
HRESULT GetRestorePosition( [out] LONG *pLeft, [out] LONG *pTop, [out] LONG *pWidth, [out] LONG *pHeight );
HRESULT HideCursor( [in] LONG HideCursor );
HRESULT IsCursorHidden( [out] LONG *CursorHidden );
}
/***************************************************************************
* IVideoWindow interface
*/
[
object,
uuid(56a868b4-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IVideoWindow : IDispatch
{
[propput] HRESULT Caption( [in] BSTR strCaption );
[propget] HRESULT Caption( [out] BSTR *strCaption );
[propput] HRESULT WindowStyle( [in] LONG WindowStyle );
[propget] HRESULT WindowStyle( [out] LONG *WindowStyle );
[propput] HRESULT WindowStyleEx( [in] LONG WindowStyleEx );
[propget] HRESULT WindowStyleEx( [out] LONG *WindowStyleEx );
[propput] HRESULT AutoShow( [in] LONG AutoShow );
[propget] HRESULT AutoShow( [out] LONG *AutoShow );
[propput] HRESULT WindowState( [in] LONG WindowState );
[propget] HRESULT WindowState( [out] LONG *WindowState );
[propput] HRESULT BackgroundPalette( [in] LONG BackgroundPalette );
[propget] HRESULT BackgroundPalette( [out] LONG *pBackgroundPalette );
[propput] HRESULT Visible( [in] LONG Visible );
[propget] HRESULT Visible( [out] LONG *pVisible );
[propput] HRESULT Left( [in] LONG Left );
[propget] HRESULT Left( [out] LONG *pLeft );
[propput] HRESULT Width( [in] LONG Width );
[propget] HRESULT Width( [out] LONG *pWidth );
[propput] HRESULT Top( [in] LONG Top );
[propget] HRESULT Top( [out] LONG *pTop );
[propput] HRESULT Height( [in] LONG Height );
[propget] HRESULT Height( [out] LONG *pHeight );
[propput] HRESULT Owner( [in] OAHWND Owner );
[propget] HRESULT Owner( [out] OAHWND *Owner );
[propput] HRESULT MessageDrain( [in] OAHWND Drain );
[propget] HRESULT MessageDrain( [out] OAHWND *Drain );
[propget] HRESULT BorderColor( [out] LONG *Color );
[propput] HRESULT BorderColor( [in] LONG Color );
[propget] HRESULT FullScreenMode( [out] LONG *FullScreenMode );
[propput] HRESULT FullScreenMode( [in] LONG FullScreenMode );
HRESULT SetWindowForeground( [in] LONG Focus );
HRESULT NotifyOwnerMessage( [in] OAHWND hwnd, [in] LONG uMsg, [in] LONG_PTR wParam, [in] LONG_PTR lParam );
HRESULT SetWindowPosition( [in] LONG Left, [in] LONG Top, [in] LONG Width, [in] LONG Height );
HRESULT GetWindowPosition( [out] LONG *pLeft, [out] LONG *pTop, [out] LONG *pWidth, [out] LONG *pHeight );
HRESULT GetMinIdealImageSize( [out] LONG *pWidth, [out] LONG *pHeight );
HRESULT GetMaxIdealImageSize( [out] LONG *pWidth, [out] LONG *pHeight );
HRESULT GetRestorePosition( [out] LONG *pLeft, [out] LONG *pTop, [out] LONG *pWidth, [out] LONG *pHeight );
HRESULT HideCursor( [in] LONG HideCursor );
HRESULT IsCursorHidden( [out] LONG *CursorHidden );
}
/*****************************************************************************
* IBasicVideo interface
*/
[
object,
uuid(56a868b5-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IBasicVideo : IDispatch
{
[propget] HRESULT AvgTimePerFrame( [out] REFTIME *pAvgTimePerFrame );
[propget] HRESULT BitRate( [out] LONG *pBitRate );
[propget] HRESULT BitErrorRate( [out] LONG *pBitErrorRate );
[propget] HRESULT VideoWidth( [out] LONG *pVideoWidth );
[propget] HRESULT VideoHeight( [out] LONG *pVideoHeight );
[propput] HRESULT SourceLeft( [in] LONG SourceLeft );
[propget] HRESULT SourceLeft( [out] LONG *pSourceLeft );
[propput] HRESULT SourceWidth( [in] LONG SourceWidth );
[propget] HRESULT SourceWidth( [out] LONG *pSourceWidth );
[propput] HRESULT SourceTop( [in] LONG SourceTop );
[propget] HRESULT SourceTop( [out] LONG *pSourceTop );
[propput] HRESULT SourceHeight( [in] LONG SourceHeight );
[propget] HRESULT SourceHeight( [out] LONG *pSourceHeight );
[propput] HRESULT DestinationLeft( [in] LONG DestinationLeft );
[propget] HRESULT DestinationLeft( [out] LONG *pDestinationLeft );
[propput] HRESULT DestinationWidth( [in] LONG DestinationWidth );
[propget] HRESULT DestinationWidth( [out] LONG *pDestinationWidth );
[propput] HRESULT DestinationTop( [in] LONG DestinationTop );
[propget] HRESULT DestinationTop( [out] LONG *pDestinationTop );
[propput] HRESULT DestinationHeight( [in] LONG DestinationHeight );
[propget] HRESULT DestinationHeight( [out] LONG *pDestinationHeight );
HRESULT SetSourcePosition( [in] LONG Left, [in] LONG Top, [in] LONG Width, [in] LONG Height );
HRESULT GetSourcePosition( [out] LONG *pLeft, [out] LONG *pTop, [out] LONG *pWidth, [out] LONG *pHeight );
HRESULT SetDefaultSourcePosition();
HRESULT SetDestinationPosition( [in] LONG Left, [in] LONG Top, [in] LONG Width, [in] LONG Height );
HRESULT GetDestinationPosition( [out] LONG *pLeft, [out] LONG *pTop, [out] LONG *pWidth, [out] LONG *pHeight );
HRESULT SetDefaultDestinationPosition();
HRESULT GetVideoSize( [out] LONG *pWidth, [out] LONG *pHeight );
HRESULT GetVideoPaletteEntries( [in] LONG StartIndex,
[in] LONG Entries,
[out] LONG *pRetrieved,
[out, size_is(Entries), length_is(*pRetrieved)] LONG *pPalette );
HRESULT GetCurrentImage( [in, out] LONG *pBufferSize,
[out, size_is(*pBufferSize), length_is(*pBufferSize)] LONG *pDIBImage );
HRESULT IsUsingDefaultSource();
HRESULT IsUsingDefaultDestination();
}
/***************************************************************************
* IBasicVideo interface
*/
[
object,
uuid(56a868b5-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IBasicVideo : IDispatch
{
[propget] HRESULT AvgTimePerFrame( [out] REFTIME *pAvgTimePerFrame );
[propget] HRESULT BitRate( [out] LONG *pBitRate );
[propget] HRESULT BitErrorRate( [out] LONG *pBitErrorRate );
[propget] HRESULT VideoWidth( [out] LONG *pVideoWidth );
[propget] HRESULT VideoHeight( [out] LONG *pVideoHeight );
[propput] HRESULT SourceLeft( [in] LONG SourceLeft );
[propget] HRESULT SourceLeft( [out] LONG *pSourceLeft );
[propput] HRESULT SourceWidth( [in] LONG SourceWidth );
[propget] HRESULT SourceWidth( [out] LONG *pSourceWidth );
[propput] HRESULT SourceTop( [in] LONG SourceTop );
[propget] HRESULT SourceTop( [out] LONG *pSourceTop );
[propput] HRESULT SourceHeight( [in] LONG SourceHeight );
[propget] HRESULT SourceHeight( [out] LONG *pSourceHeight );
[propput] HRESULT DestinationLeft( [in] LONG DestinationLeft );
[propget] HRESULT DestinationLeft( [out] LONG *pDestinationLeft );
[propput] HRESULT DestinationWidth( [in] LONG DestinationWidth );
[propget] HRESULT DestinationWidth( [out] LONG *pDestinationWidth );
[propput] HRESULT DestinationTop( [in] LONG DestinationTop );
[propget] HRESULT DestinationTop( [out] LONG *pDestinationTop );
[propput] HRESULT DestinationHeight( [in] LONG DestinationHeight );
[propget] HRESULT DestinationHeight( [out] LONG *pDestinationHeight );
HRESULT SetSourcePosition( [in] LONG Left, [in] LONG Top, [in] LONG Width, [in] LONG Height );
HRESULT GetSourcePosition( [out] LONG *pLeft, [out] LONG *pTop, [out] LONG *pWidth, [out] LONG *pHeight );
HRESULT SetDefaultSourcePosition();
HRESULT SetDestinationPosition( [in] LONG Left, [in] LONG Top, [in] LONG Width, [in] LONG Height );
HRESULT GetDestinationPosition( [out] LONG *pLeft, [out] LONG *pTop, [out] LONG *pWidth, [out] LONG *pHeight );
HRESULT SetDefaultDestinationPosition();
HRESULT GetVideoSize( [out] LONG *pWidth, [out] LONG *pHeight );
HRESULT GetVideoPaletteEntries( [in] LONG StartIndex,
[in] LONG Entries,
[out] LONG *pRetrieved,
[out, size_is(Entries), length_is(*pRetrieved)] LONG *pPalette );
HRESULT GetCurrentImage( [in, out] LONG *pBufferSize,
[out, size_is(*pBufferSize), length_is(*pBufferSize)] LONG *pDIBImage );
HRESULT IsUsingDefaultSource();
HRESULT IsUsingDefaultDestination();
}
[
uuid(329bb360-f6ea-11d1-9038-00a0c9697298),
helpstring("IBasicVideo2"),
odl
]
[
uuid(329bb360-f6ea-11d1-9038-00a0c9697298),
helpstring("IBasicVideo2"),
odl
]
interface IBasicVideo2 : IBasicVideo
{
HRESULT GetPreferredAspectRatio([out] LONG *plAspectX, [out] LONG *plAspectY);
}
interface IBasicVideo2 : IBasicVideo
{
HRESULT GetPreferredAspectRatio([out] LONG *plAspectX, [out] LONG *plAspectY);
}
/*****************************************************************************
* IMediaEvent interface
*/
[
object,
uuid(56a868b6-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IMediaEvent : IDispatch
{
HRESULT GetEventHandle( [out] OAEVENT *hEvent );
HRESULT GetEvent( [out] LONG *lEventCode, [out] LONG_PTR *lParam1, [out] LONG_PTR *lParam2, [in] LONG msTimeout );
HRESULT WaitForCompletion( [in] LONG msTimeout, [out] LONG *pEvCode );
HRESULT CancelDefaultHandling( [in] LONG lEvCode );
HRESULT RestoreDefaultHandling( [in] LONG lEvCode );
HRESULT FreeEventParams( [in] LONG lEvCode, [in] LONG_PTR lParam1, [in] LONG_PTR lParam2 );
}
/***************************************************************************
* IMediaEvent interface
*/
[
object,
uuid(56a868b6-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IMediaEvent : IDispatch
{
HRESULT GetEventHandle( [out] OAEVENT *hEvent );
HRESULT GetEvent( [out] LONG *lEventCode, [out] LONG_PTR *lParam1, [out] LONG_PTR *lParam2, [in] LONG msTimeout );
HRESULT WaitForCompletion( [in] LONG msTimeout, [out] LONG *pEvCode );
HRESULT CancelDefaultHandling( [in] LONG lEvCode );
HRESULT RestoreDefaultHandling( [in] LONG lEvCode );
HRESULT FreeEventParams( [in] LONG lEvCode, [in] LONG_PTR lParam1, [in] LONG_PTR lParam2 );
}
/*****************************************************************************
* IMediaEventEx interface
*/
[
object,
uuid(56a868c0-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IMediaEventEx : IMediaEvent
{
HRESULT SetNotifyWindow( [in] OAHWND hwnd, [in] LONG lMsg, [in] LONG_PTR lInstanceData );
HRESULT SetNotifyFlags( [in] LONG lNoNotifyFlags );
HRESULT GetNotifyFlags( [out] LONG *lplNoNotifyFlags );
}
/***************************************************************************
* IMediaEventEx interface
*/
[
object,
uuid(56a868c0-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IMediaEventEx : IMediaEvent
{
HRESULT SetNotifyWindow( [in] OAHWND hwnd, [in] LONG lMsg, [in] LONG_PTR lInstanceData );
HRESULT SetNotifyFlags( [in] LONG lNoNotifyFlags );
HRESULT GetNotifyFlags( [out] LONG *lplNoNotifyFlags );
}
/*****************************************************************************
* IMediaPosition interface
*/
[
object,
uuid(56a868b2-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IMediaPosition : IDispatch
{
HRESULT get_Duration( [out] REFTIME *plength );
HRESULT put_CurrentPosition( [in] REFTIME llTime );
HRESULT get_CurrentPosition( [out] REFTIME *pllTime );
HRESULT get_StopTime( [out] REFTIME *pllTime );
HRESULT put_StopTime( [in] REFTIME llTime );
HRESULT get_PrerollTime( [out] REFTIME *pllTime );
HRESULT put_PrerollTime( [in] REFTIME llTime );
HRESULT put_Rate( [in] double dRate );
HRESULT get_Rate( [out] double *pdRate );
HRESULT CanSeekForward( [out] LONG *pCanSeekForward );
HRESULT CanSeekBackward( [out] LONG *pCanSeekBackward );
}
/***************************************************************************
* IMediaPosition interface
*/
[
object,
uuid(56a868b2-0ad4-11ce-b03a-0020af0ba770),
pointer_default(unique)
]
interface IMediaPosition : IDispatch
{
HRESULT get_Duration( [out] REFTIME *plength );
HRESULT put_CurrentPosition( [in] REFTIME llTime );
HRESULT get_CurrentPosition( [out] REFTIME *pllTime );
HRESULT get_StopTime( [out] REFTIME *pllTime );
HRESULT put_StopTime( [in] REFTIME llTime );
HRESULT get_PrerollTime( [out] REFTIME *pllTime );
HRESULT put_PrerollTime( [in] REFTIME llTime );
HRESULT put_Rate( [in] double dRate );
HRESULT get_Rate( [out] double *pdRate );
HRESULT CanSeekForward( [out] LONG *pCanSeekForward );
HRESULT CanSeekBackward( [out] LONG *pCanSeekBackward );
}
} /* library QuartzTypeLib */

View file

@ -16,6 +16,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
import "unknwn.idl";
import "objidl.idl";
#include <devenum.idl>

View file

@ -768,10 +768,15 @@ typedef struct _DEBUG_EVENT {
typedef struct _OVERLAPPED {
ULONG_PTR Internal;
ULONG_PTR InternalHigh;
DWORD Offset;
DWORD OffsetHigh;
union {
struct {
DWORD Offset;
DWORD OffsetHigh;
} DUMMYSTRUCTNAME;
PVOID Pointer;
} DUMMYUNIONNAME;
HANDLE hEvent;
} OVERLAPPED,*POVERLAPPED,*LPOVERLAPPED;
} OVERLAPPED, *POVERLAPPED, *LPOVERLAPPED;
typedef struct _STARTUPINFOA {
DWORD cb;

View file

@ -0,0 +1,660 @@
/*
* Header file for Wine's strmbase implementation
*
* Copyright 2003 Robert Shearman
* Copyright 2010 Aric Stewart, CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
HRESULT WINAPI CopyMediaType(AM_MEDIA_TYPE * pDest, const AM_MEDIA_TYPE *pSrc);
void WINAPI FreeMediaType(AM_MEDIA_TYPE * pMediaType);
AM_MEDIA_TYPE * WINAPI CreateMediaType(AM_MEDIA_TYPE const * pSrc);
void WINAPI DeleteMediaType(AM_MEDIA_TYPE * pMediaType);
/* Pin functions */
typedef struct BasePin
{
IPin IPin_iface;
LONG refCount;
LPCRITICAL_SECTION pCritSec;
PIN_INFO pinInfo;
IPin * pConnectedTo;
AM_MEDIA_TYPE mtCurrent;
REFERENCE_TIME tStart;
REFERENCE_TIME tStop;
double dRate;
const struct BasePinFuncTable* pFuncsTable;
} BasePin;
typedef HRESULT (WINAPI *BasePin_CheckMediaType)(BasePin *This, const AM_MEDIA_TYPE *pmt);
typedef HRESULT (WINAPI *BasePin_AttemptConnection)(BasePin *This, IPin *pReceivePin, const AM_MEDIA_TYPE *pmt);
typedef LONG (WINAPI *BasePin_GetMediaTypeVersion)(BasePin *This);
typedef HRESULT (WINAPI *BasePin_GetMediaType)(BasePin *This, int iPosition, AM_MEDIA_TYPE *amt);
typedef struct BasePinFuncTable {
/* Required for Input Pins*/
BasePin_CheckMediaType pfnCheckMediaType;
/* Required for Output Pins*/
BasePin_AttemptConnection pfnAttemptConnection;
/* Required for BasePinImpl_EnumMediaTypes */
BasePin_GetMediaTypeVersion pfnGetMediaTypeVersion;
BasePin_GetMediaType pfnGetMediaType;
} BasePinFuncTable;
typedef struct BaseOutputPin
{
/* inheritance C style! */
BasePin pin;
IMemInputPin * pMemInputPin;
IMemAllocator * pAllocator;
const struct BaseOutputPinFuncTable* pFuncsTable;
} BaseOutputPin;
typedef HRESULT (WINAPI *BaseOutputPin_DecideBufferSize)(BaseOutputPin *This, IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest);
typedef HRESULT (WINAPI *BaseOutputPin_DecideAllocator)(BaseOutputPin *This, IMemInputPin *pPin, IMemAllocator **pAlloc);
typedef HRESULT (WINAPI *BaseOutputPin_BreakConnect)(BaseOutputPin * This);
typedef struct BaseOutputPinFuncTable {
/* Required for BaseOutputPinImpl_DecideAllocator */
BaseOutputPin_DecideBufferSize pfnDecideBufferSize;
/* Required for BaseOutputPinImpl_AttemptConnection */
BaseOutputPin_DecideAllocator pfnDecideAllocator;
BaseOutputPin_BreakConnect pfnBreakConnect;
} BaseOutputPinFuncTable;
typedef struct BaseInputPin
{
/* inheritance C style! */
BasePin pin;
IMemInputPin IMemInputPin_iface;
IMemAllocator * pAllocator;
BOOL flushing, end_of_stream;
IMemAllocator *preferred_allocator;
const struct BaseInputPinFuncTable* pFuncsTable;
} BaseInputPin;
typedef HRESULT (WINAPI *BaseInputPin_Receive)(BaseInputPin *This, IMediaSample *pSample);
typedef struct BaseInputPinFuncTable {
/* Optional */
BaseInputPin_Receive pfnReceive;
} BaseInputPinFuncTable;
/* Base Pin */
HRESULT WINAPI BasePinImpl_GetMediaType(BasePin *This, int iPosition, AM_MEDIA_TYPE *pmt);
LONG WINAPI BasePinImpl_GetMediaTypeVersion(BasePin *This);
ULONG WINAPI BasePinImpl_AddRef(IPin * iface);
HRESULT WINAPI BasePinImpl_Disconnect(IPin * iface);
HRESULT WINAPI BasePinImpl_ConnectedTo(IPin * iface, IPin ** ppPin);
HRESULT WINAPI BasePinImpl_ConnectionMediaType(IPin * iface, AM_MEDIA_TYPE * pmt);
HRESULT WINAPI BasePinImpl_QueryPinInfo(IPin * iface, PIN_INFO * pInfo);
HRESULT WINAPI BasePinImpl_QueryDirection(IPin * iface, PIN_DIRECTION * pPinDir);
HRESULT WINAPI BasePinImpl_QueryId(IPin * iface, LPWSTR * Id);
HRESULT WINAPI BasePinImpl_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt);
HRESULT WINAPI BasePinImpl_EnumMediaTypes(IPin * iface, IEnumMediaTypes ** ppEnum);
HRESULT WINAPI BasePinImpl_QueryInternalConnections(IPin * iface, IPin ** apPin, ULONG * cPin);
HRESULT WINAPI BasePinImpl_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
/* Base Output Pin */
HRESULT WINAPI BaseOutputPinImpl_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv);
ULONG WINAPI BaseOutputPinImpl_Release(IPin * iface);
HRESULT WINAPI BaseOutputPinImpl_Connect(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt);
HRESULT WINAPI BaseOutputPinImpl_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt);
HRESULT WINAPI BaseOutputPinImpl_Disconnect(IPin * iface);
HRESULT WINAPI BaseOutputPinImpl_EndOfStream(IPin * iface);
HRESULT WINAPI BaseOutputPinImpl_BeginFlush(IPin * iface);
HRESULT WINAPI BaseOutputPinImpl_EndFlush(IPin * iface);
HRESULT WINAPI BaseOutputPinImpl_GetDeliveryBuffer(BaseOutputPin * This, IMediaSample ** ppSample, REFERENCE_TIME * tStart, REFERENCE_TIME * tStop, DWORD dwFlags);
HRESULT WINAPI BaseOutputPinImpl_Deliver(BaseOutputPin * This, IMediaSample * pSample);
HRESULT WINAPI BaseOutputPinImpl_BreakConnect(BaseOutputPin * This);
HRESULT WINAPI BaseOutputPinImpl_Active(BaseOutputPin * This);
HRESULT WINAPI BaseOutputPinImpl_Inactive(BaseOutputPin * This);
HRESULT WINAPI BaseOutputPinImpl_InitAllocator(BaseOutputPin *This, IMemAllocator **pMemAlloc);
HRESULT WINAPI BaseOutputPinImpl_DecideAllocator(BaseOutputPin *This, IMemInputPin *pPin, IMemAllocator **pAlloc);
HRESULT WINAPI BaseOutputPinImpl_AttemptConnection(BasePin *This, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt);
HRESULT WINAPI BaseOutputPin_Construct(const IPinVtbl *OutputPin_Vtbl, LONG outputpin_size, const PIN_INFO * pPinInfo, const BasePinFuncTable* pBaseFuncsTable, const BaseOutputPinFuncTable* pBaseOutputFuncsTable, LPCRITICAL_SECTION pCritSec, IPin ** ppPin);
/* Base Input Pin */
HRESULT WINAPI BaseInputPinImpl_QueryInterface(IPin * iface, REFIID riid, LPVOID * ppv);
ULONG WINAPI BaseInputPinImpl_Release(IPin * iface);
HRESULT WINAPI BaseInputPinImpl_Connect(IPin * iface, IPin * pConnector, const AM_MEDIA_TYPE * pmt);
HRESULT WINAPI BaseInputPinImpl_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt);
HRESULT WINAPI BaseInputPinImpl_QueryAccept(IPin * iface, const AM_MEDIA_TYPE * pmt);
HRESULT WINAPI BaseInputPinImpl_EndOfStream(IPin * iface);
HRESULT WINAPI BaseInputPinImpl_BeginFlush(IPin * iface);
HRESULT WINAPI BaseInputPinImpl_EndFlush(IPin * iface);
HRESULT WINAPI BaseInputPinImpl_NewSegment(IPin * iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
HRESULT BaseInputPin_Construct(const IPinVtbl *InputPin_Vtbl, const PIN_INFO * pPinInfo, const BasePinFuncTable* pBaseFuncsTable, const BaseInputPinFuncTable* pBaseInputFuncsTable, LPCRITICAL_SECTION pCritSec, IMemAllocator *, IPin ** ppPin);
typedef struct BaseFilter
{
IBaseFilter IBaseFilter_iface;
LONG refCount;
CRITICAL_SECTION csFilter;
FILTER_STATE state;
REFERENCE_TIME rtStreamStart;
IReferenceClock * pClock;
FILTER_INFO filterInfo;
CLSID clsid;
LONG pinVersion;
const struct BaseFilterFuncTable* pFuncsTable;
} BaseFilter;
typedef IPin* (WINAPI *BaseFilter_GetPin)(BaseFilter* iface, int iPosition);
typedef LONG (WINAPI *BaseFilter_GetPinCount)(BaseFilter* iface);
typedef LONG (WINAPI *BaseFilter_GetPinVersion)(BaseFilter* iface);
typedef struct BaseFilterFuncTable {
/* Required */
BaseFilter_GetPin pfnGetPin;
BaseFilter_GetPinCount pfnGetPinCount;
} BaseFilterFuncTable;
HRESULT WINAPI BaseFilterImpl_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv);
ULONG WINAPI BaseFilterImpl_AddRef(IBaseFilter * iface);
ULONG WINAPI BaseFilterImpl_Release(IBaseFilter * iface);
HRESULT WINAPI BaseFilterImpl_GetClassID(IBaseFilter * iface, CLSID * pClsid);
HRESULT WINAPI BaseFilterImpl_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState );
HRESULT WINAPI BaseFilterImpl_SetSyncSource(IBaseFilter * iface, IReferenceClock *pClock);
HRESULT WINAPI BaseFilterImpl_GetSyncSource(IBaseFilter * iface, IReferenceClock **ppClock);
HRESULT WINAPI BaseFilterImpl_EnumPins(IBaseFilter * iface, IEnumPins **ppEnum);
HRESULT WINAPI BaseFilterImpl_QueryFilterInfo(IBaseFilter * iface, FILTER_INFO *pInfo);
HRESULT WINAPI BaseFilterImpl_JoinFilterGraph(IBaseFilter * iface, IFilterGraph *pGraph, LPCWSTR pName );
HRESULT WINAPI BaseFilterImpl_QueryVendorInfo(IBaseFilter * iface, LPWSTR *pVendorInfo);
LONG WINAPI BaseFilterImpl_GetPinVersion(BaseFilter* This);
VOID WINAPI BaseFilterImpl_IncrementPinVersion(BaseFilter* This);
HRESULT WINAPI BaseFilter_Init(BaseFilter * This, const IBaseFilterVtbl *Vtbl, const CLSID *pClsid, DWORD_PTR DebugInfo, const BaseFilterFuncTable* pBaseFuncsTable);
/* Enums */
HRESULT WINAPI EnumMediaTypes_Construct(BasePin *iface, BasePin_GetMediaType enumFunc, BasePin_GetMediaTypeVersion versionFunc, IEnumMediaTypes ** ppEnum);
HRESULT WINAPI EnumPins_Construct(BaseFilter *base, BaseFilter_GetPin receive_pin, BaseFilter_GetPinCount receive_pincount, BaseFilter_GetPinVersion receive_version, IEnumPins ** ppEnum);
/* Transform Filter */
typedef struct TransformFilter
{
BaseFilter filter;
IPin **ppPins;
ULONG npins;
AM_MEDIA_TYPE pmt;
CRITICAL_SECTION csReceive;
const struct TransformFilterFuncTable * pFuncsTable;
struct QualityControlImpl *qcimpl;
/* IMediaSeeking and IMediaPosition are implemented by ISeekingPassThru */
IUnknown *seekthru_unk;
} TransformFilter;
typedef HRESULT (WINAPI *TransformFilter_DecideBufferSize) (TransformFilter *iface, IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest);
typedef HRESULT (WINAPI *TransformFilter_StartStreaming) (TransformFilter *iface);
typedef HRESULT (WINAPI *TransformFilter_StopStreaming) (TransformFilter *iface);
typedef HRESULT (WINAPI *TransformFilter_Receive) (TransformFilter* iface, IMediaSample* pIn);
typedef HRESULT (WINAPI *TransformFilter_CompleteConnect) (TransformFilter *iface, PIN_DIRECTION dir, IPin *pPin);
typedef HRESULT (WINAPI *TransformFilter_BreakConnect) (TransformFilter *iface, PIN_DIRECTION dir);
typedef HRESULT (WINAPI *TransformFilter_SetMediaType) (TransformFilter *iface, PIN_DIRECTION dir, const AM_MEDIA_TYPE *pMediaType);
typedef HRESULT (WINAPI *TransformFilter_CheckInputType) (TransformFilter *iface, const AM_MEDIA_TYPE *pMediaType);
typedef HRESULT (WINAPI *TransformFilter_EndOfStream) (TransformFilter *iface);
typedef HRESULT (WINAPI *TransformFilter_BeginFlush) (TransformFilter *iface);
typedef HRESULT (WINAPI *TransformFilter_EndFlush) (TransformFilter *iface);
typedef HRESULT (WINAPI *TransformFilter_NewSegment) (TransformFilter *iface,
REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
typedef HRESULT (WINAPI *TransformFilter_Notify) (TransformFilter *iface, IBaseFilter *sender, Quality qm);
typedef struct TransformFilterFuncTable {
/* Required */
TransformFilter_DecideBufferSize pfnDecideBufferSize;
/* Optional */
TransformFilter_StartStreaming pfnStartStreaming;
TransformFilter_Receive pfnReceive;
TransformFilter_StopStreaming pfnStopStreaming;
TransformFilter_CheckInputType pfnCheckInputType;
TransformFilter_SetMediaType pfnSetMediaType;
TransformFilter_CompleteConnect pfnCompleteConnect;
TransformFilter_BreakConnect pfnBreakConnect;
TransformFilter_EndOfStream pfnEndOfStream;
TransformFilter_BeginFlush pfnBeginFlush;
TransformFilter_EndFlush pfnEndFlush;
TransformFilter_NewSegment pfnNewSegment;
TransformFilter_Notify pfnNotify;
} TransformFilterFuncTable;
HRESULT WINAPI TransformFilterImpl_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv);
ULONG WINAPI TransformFilterImpl_Release(IBaseFilter * iface);
HRESULT WINAPI TransformFilterImpl_Stop(IBaseFilter * iface);
HRESULT WINAPI TransformFilterImpl_Pause(IBaseFilter * iface);
HRESULT WINAPI TransformFilterImpl_Run(IBaseFilter * iface, REFERENCE_TIME tStart);
HRESULT WINAPI TransformFilterImpl_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin);
HRESULT WINAPI TransformFilterImpl_Notify(TransformFilter *iface, IBaseFilter *sender, Quality qm);
HRESULT TransformFilter_Construct( const IBaseFilterVtbl *filterVtbl, LONG filter_size, const CLSID* pClsid, const TransformFilterFuncTable* pFuncsTable, IBaseFilter ** ppTransformFilter);
/* Source Seeking */
typedef HRESULT (WINAPI *SourceSeeking_ChangeRate)(IMediaSeeking *iface);
typedef HRESULT (WINAPI *SourceSeeking_ChangeStart)(IMediaSeeking *iface);
typedef HRESULT (WINAPI *SourceSeeking_ChangeStop)(IMediaSeeking *iface);
typedef struct SourceSeeking
{
IMediaSeeking IMediaSeeking_iface;
ULONG refCount;
SourceSeeking_ChangeStop fnChangeStop;
SourceSeeking_ChangeStart fnChangeStart;
SourceSeeking_ChangeRate fnChangeRate;
DWORD dwCapabilities;
double dRate;
LONGLONG llCurrent, llStop, llDuration;
GUID timeformat;
PCRITICAL_SECTION crst;
} SourceSeeking;
HRESULT SourceSeeking_Init(SourceSeeking *pSeeking, const IMediaSeekingVtbl *Vtbl, SourceSeeking_ChangeStop fnChangeStop, SourceSeeking_ChangeStart fnChangeStart, SourceSeeking_ChangeRate fnChangeRate, PCRITICAL_SECTION crit_sect);
HRESULT WINAPI SourceSeekingImpl_GetCapabilities(IMediaSeeking * iface, DWORD * pCapabilities);
HRESULT WINAPI SourceSeekingImpl_CheckCapabilities(IMediaSeeking * iface, DWORD * pCapabilities);
HRESULT WINAPI SourceSeekingImpl_IsFormatSupported(IMediaSeeking * iface, const GUID * pFormat);
HRESULT WINAPI SourceSeekingImpl_QueryPreferredFormat(IMediaSeeking * iface, GUID * pFormat);
HRESULT WINAPI SourceSeekingImpl_GetTimeFormat(IMediaSeeking * iface, GUID * pFormat);
HRESULT WINAPI SourceSeekingImpl_IsUsingTimeFormat(IMediaSeeking * iface, const GUID * pFormat);
HRESULT WINAPI SourceSeekingImpl_SetTimeFormat(IMediaSeeking * iface, const GUID * pFormat);
HRESULT WINAPI SourceSeekingImpl_GetDuration(IMediaSeeking * iface, LONGLONG * pDuration);
HRESULT WINAPI SourceSeekingImpl_GetStopPosition(IMediaSeeking * iface, LONGLONG * pStop);
HRESULT WINAPI SourceSeekingImpl_GetCurrentPosition(IMediaSeeking * iface, LONGLONG * pCurrent);
HRESULT WINAPI SourceSeekingImpl_ConvertTimeFormat(IMediaSeeking * iface, LONGLONG * pTarget, const GUID * pTargetFormat, LONGLONG Source, const GUID * pSourceFormat);
HRESULT WINAPI SourceSeekingImpl_SetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, DWORD dwCurrentFlags, LONGLONG * pStop, DWORD dwStopFlags);
HRESULT WINAPI SourceSeekingImpl_GetPositions(IMediaSeeking * iface, LONGLONG * pCurrent, LONGLONG * pStop);
HRESULT WINAPI SourceSeekingImpl_GetAvailable(IMediaSeeking * iface, LONGLONG * pEarliest, LONGLONG * pLatest);
HRESULT WINAPI SourceSeekingImpl_SetRate(IMediaSeeking * iface, double dRate);
HRESULT WINAPI SourceSeekingImpl_GetRate(IMediaSeeking * iface, double * dRate);
HRESULT WINAPI SourceSeekingImpl_GetPreroll(IMediaSeeking * iface, LONGLONG * pPreroll);
/* PosPassThru */
HRESULT WINAPI RendererPosPassThru_RegisterMediaTime(IUnknown *iface, REFERENCE_TIME start);
HRESULT WINAPI RendererPosPassThru_ResetMediaTime(IUnknown *iface);
HRESULT WINAPI RendererPosPassThru_EOS(IUnknown *iface);
HRESULT WINAPI CreatePosPassThru(IUnknown* pUnkOuter, BOOL bRenderer, IPin *pPin, IUnknown **ppPassThru);
HRESULT WINAPI PosPassThru_Construct(IUnknown* pUnkOuter, LPVOID *ppPassThru);
/* Filter Registration */
typedef REGPINTYPES AMOVIESETUP_MEDIATYPE;
typedef REGFILTERPINS AMOVIESETUP_PIN;
typedef struct AMOVIESETUP_FILTER {
const CLSID *clsid;
const WCHAR *name;
DWORD merit;
UINT pins;
const AMOVIESETUP_PIN *pPin;
} AMOVIESETUP_FILTER, *LPAMOVIESETUP_FILTER;
typedef IUnknown *(CALLBACK *LPFNNewCOMObject)(LPUNKNOWN pUnkOuter, HRESULT *phr);
typedef void (CALLBACK *LPFNInitRoutine)(BOOL bLoading, const CLSID *rclsid);
typedef struct tagFactoryTemplate {
const WCHAR *m_Name;
const CLSID *m_ClsID;
LPFNNewCOMObject m_lpfnNew;
LPFNInitRoutine m_lpfnInit;
const AMOVIESETUP_FILTER *m_pAMovieSetup_Filter;
} FactoryTemplate;
HRESULT WINAPI AMovieDllRegisterServer2(BOOL bRegister);
HRESULT WINAPI AMovieSetupRegisterFilter2(const AMOVIESETUP_FILTER *pFilter, IFilterMapper2 *pIFM2, BOOL bRegister);
/* Output Queue */
typedef struct tagOutputQueue {
CRITICAL_SECTION csQueue;
BaseOutputPin * pInputPin;
HANDLE hThread;
HANDLE hProcessQueue;
LONG lBatchSize;
BOOL bBatchExact;
BOOL bTerminate;
BOOL bSendAnyway;
struct list *SampleList;
const struct OutputQueueFuncTable* pFuncsTable;
} OutputQueue;
typedef DWORD (WINAPI *OutputQueue_ThreadProc)(OutputQueue *This);
typedef struct OutputQueueFuncTable
{
OutputQueue_ThreadProc pfnThreadProc;
} OutputQueueFuncTable;
HRESULT WINAPI OutputQueue_Construct( BaseOutputPin *pInputPin, BOOL bAuto,
BOOL bQueue, LONG lBatchSize, BOOL bBatchExact, DWORD dwPriority,
const OutputQueueFuncTable* pFuncsTable, OutputQueue **ppOutputQueue );
HRESULT WINAPI OutputQueue_Destroy(OutputQueue *pOutputQueue);
HRESULT WINAPI OutputQueue_ReceiveMultiple(OutputQueue *pOutputQueue, IMediaSample **ppSamples, LONG nSamples, LONG *nSamplesProcessed);
HRESULT WINAPI OutputQueue_Receive(OutputQueue *pOutputQueue, IMediaSample *pSample);
VOID WINAPI OutputQueue_EOS(OutputQueue *pOutputQueue);
VOID WINAPI OutputQueue_SendAnyway(OutputQueue *pOutputQueue);
DWORD WINAPI OutputQueueImpl_ThreadProc(OutputQueue *pOutputQueue);
typedef struct tagBaseWindow
{
HWND hWnd;
LONG Width;
LONG Height;
HINSTANCE hInstance;
LPWSTR pClassName;
DWORD ClassStyles;
DWORD WindowStyles;
DWORD WindowStylesEx;
HDC hDC;
const struct BaseWindowFuncTable* pFuncsTable;
} BaseWindow;
typedef LPWSTR (WINAPI *BaseWindow_GetClassWindowStyles)(BaseWindow *This, DWORD *pClassStyles, DWORD *pWindowStyles, DWORD *pWindowStylesEx);
typedef RECT (WINAPI *BaseWindow_GetDefaultRect)(BaseWindow *This);
typedef BOOL (WINAPI *BaseWindow_PossiblyEatMessage)(BaseWindow *This, UINT uMsg, WPARAM wParam, LPARAM lParam);
typedef LRESULT (WINAPI *BaseWindow_OnReceiveMessage)(BaseWindow *This, HWND hwnd, INT uMsg, WPARAM wParam, LPARAM lParam);
typedef BOOL (WINAPI *BaseWindow_OnSize)(BaseWindow *This, LONG Height, LONG Width);
typedef struct BaseWindowFuncTable
{
/* Required */
BaseWindow_GetClassWindowStyles pfnGetClassWindowStyles;
BaseWindow_GetDefaultRect pfnGetDefaultRect;
/* Optional, WinProc Related */
BaseWindow_OnReceiveMessage pfnOnReceiveMessage;
BaseWindow_PossiblyEatMessage pfnPossiblyEatMessage;
BaseWindow_OnSize pfnOnSize;
} BaseWindowFuncTable;
HRESULT WINAPI BaseWindow_Init(BaseWindow *pBaseWindow, const BaseWindowFuncTable* pFuncsTable);
HRESULT WINAPI BaseWindow_Destroy(BaseWindow *pBaseWindow);
HRESULT WINAPI BaseWindowImpl_PrepareWindow(BaseWindow *This);
HRESULT WINAPI BaseWindowImpl_DoneWithWindow(BaseWindow *This);
RECT WINAPI BaseWindowImpl_GetDefaultRect(BaseWindow *This);
LRESULT WINAPI BaseWindowImpl_OnReceiveMessage(BaseWindow *This, HWND hwnd, INT uMsg, WPARAM wParam, LPARAM lParam);
BOOL WINAPI BaseWindowImpl_OnSize(BaseWindow *This, LONG Height, LONG Width);
typedef struct{
ITypeInfo *pTypeInfo;
} BaseDispatch;
HRESULT WINAPI BaseDispatch_Init(BaseDispatch *This, REFIID riid);
HRESULT WINAPI BaseDispatch_Destroy(BaseDispatch *This);
HRESULT WINAPI BaseDispatchImpl_GetIDsOfNames(BaseDispatch *This, REFIID riid, OLECHAR **rgszNames, UINT cNames, LCID lcid, DISPID *rgdispid);
HRESULT WINAPI BaseDispatchImpl_GetTypeInfo(BaseDispatch *This, REFIID riid, UINT itinfo, LCID lcid, ITypeInfo **pptinfo);
HRESULT WINAPI BaseDispatchImpl_GetTypeInfoCount(BaseDispatch *This, UINT *pctinfo);
#ifdef __IVideoWindow_FWD_DEFINED__
typedef struct tagBaseControlWindow
{
BaseWindow baseWindow;
IVideoWindow IVideoWindow_iface;
BaseDispatch baseDispatch;
BOOL AutoShow;
HWND hwndDrain;
HWND hwndOwner;
BaseFilter* pFilter;
CRITICAL_SECTION* pInterfaceLock;
BasePin* pPin;
} BaseControlWindow;
HRESULT WINAPI BaseControlWindow_Init(BaseControlWindow *pControlWindow, const IVideoWindowVtbl *lpVtbl, BaseFilter *owner, CRITICAL_SECTION *lock, BasePin* pPin, const BaseWindowFuncTable* pFuncsTable);
HRESULT WINAPI BaseControlWindow_Destroy(BaseControlWindow *pControlWindow);
BOOL WINAPI BaseControlWindowImpl_PossiblyEatMessage(BaseWindow *This, UINT uMsg, WPARAM wParam, LPARAM lParam);
HRESULT WINAPI BaseControlWindowImpl_GetTypeInfoCount(IVideoWindow *iface, UINT*pctinfo);
HRESULT WINAPI BaseControlWindowImpl_GetTypeInfo(IVideoWindow *iface, UINT iTInfo, LCID lcid, ITypeInfo**ppTInfo);
HRESULT WINAPI BaseControlWindowImpl_GetIDsOfNames(IVideoWindow *iface, REFIID riid, LPOLESTR*rgszNames, UINT cNames, LCID lcid, DISPID*rgDispId);
HRESULT WINAPI BaseControlWindowImpl_Invoke(IVideoWindow *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS*pDispParams, VARIANT*pVarResult, EXCEPINFO*pExepInfo, UINT*puArgErr);
HRESULT WINAPI BaseControlWindowImpl_put_Caption(IVideoWindow *iface, BSTR strCaption);
HRESULT WINAPI BaseControlWindowImpl_get_Caption(IVideoWindow *iface, BSTR *strCaption);
HRESULT WINAPI BaseControlWindowImpl_put_WindowStyle(IVideoWindow *iface, LONG WindowStyle);
HRESULT WINAPI BaseControlWindowImpl_get_WindowStyle(IVideoWindow *iface, LONG *WindowStyle);
HRESULT WINAPI BaseControlWindowImpl_put_WindowStyleEx(IVideoWindow *iface, LONG WindowStyleEx);
HRESULT WINAPI BaseControlWindowImpl_get_WindowStyleEx(IVideoWindow *iface, LONG *WindowStyleEx);
HRESULT WINAPI BaseControlWindowImpl_put_AutoShow(IVideoWindow *iface, LONG AutoShow);
HRESULT WINAPI BaseControlWindowImpl_get_AutoShow(IVideoWindow *iface, LONG *AutoShow);
HRESULT WINAPI BaseControlWindowImpl_put_WindowState(IVideoWindow *iface, LONG WindowState);
HRESULT WINAPI BaseControlWindowImpl_get_WindowState(IVideoWindow *iface, LONG *WindowState);
HRESULT WINAPI BaseControlWindowImpl_put_BackgroundPalette(IVideoWindow *iface, LONG BackgroundPalette);
HRESULT WINAPI BaseControlWindowImpl_get_BackgroundPalette(IVideoWindow *iface, LONG *pBackgroundPalette);
HRESULT WINAPI BaseControlWindowImpl_put_Visible(IVideoWindow *iface, LONG Visible);
HRESULT WINAPI BaseControlWindowImpl_get_Visible(IVideoWindow *iface, LONG *pVisible);
HRESULT WINAPI BaseControlWindowImpl_put_Left(IVideoWindow *iface, LONG Left);
HRESULT WINAPI BaseControlWindowImpl_get_Left(IVideoWindow *iface, LONG *pLeft);
HRESULT WINAPI BaseControlWindowImpl_put_Width(IVideoWindow *iface, LONG Width);
HRESULT WINAPI BaseControlWindowImpl_get_Width(IVideoWindow *iface, LONG *pWidth);
HRESULT WINAPI BaseControlWindowImpl_put_Top(IVideoWindow *iface, LONG Top);
HRESULT WINAPI BaseControlWindowImpl_get_Top(IVideoWindow *iface, LONG *pTop);
HRESULT WINAPI BaseControlWindowImpl_put_Height(IVideoWindow *iface, LONG Height);
HRESULT WINAPI BaseControlWindowImpl_get_Height(IVideoWindow *iface, LONG *pHeight);
HRESULT WINAPI BaseControlWindowImpl_put_Owner(IVideoWindow *iface, OAHWND Owner);
HRESULT WINAPI BaseControlWindowImpl_get_Owner(IVideoWindow *iface, OAHWND *Owner);
HRESULT WINAPI BaseControlWindowImpl_put_MessageDrain(IVideoWindow *iface, OAHWND Drain);
HRESULT WINAPI BaseControlWindowImpl_get_MessageDrain(IVideoWindow *iface, OAHWND *Drain);
HRESULT WINAPI BaseControlWindowImpl_get_BorderColor(IVideoWindow *iface, LONG *Color);
HRESULT WINAPI BaseControlWindowImpl_put_BorderColor(IVideoWindow *iface, LONG Color);
HRESULT WINAPI BaseControlWindowImpl_get_FullScreenMode(IVideoWindow *iface, LONG *FullScreenMode);
HRESULT WINAPI BaseControlWindowImpl_put_FullScreenMode(IVideoWindow *iface, LONG FullScreenMode);
HRESULT WINAPI BaseControlWindowImpl_SetWindowForeground(IVideoWindow *iface, LONG Focus);
HRESULT WINAPI BaseControlWindowImpl_SetWindowPosition(IVideoWindow *iface, LONG Left, LONG Top, LONG Width, LONG Height);
HRESULT WINAPI BaseControlWindowImpl_GetWindowPosition(IVideoWindow *iface, LONG *pLeft, LONG *pTop, LONG *pWidth, LONG *pHeight);
HRESULT WINAPI BaseControlWindowImpl_NotifyOwnerMessage(IVideoWindow *iface, OAHWND hwnd, LONG uMsg, LONG_PTR wParam, LONG_PTR lParam);
HRESULT WINAPI BaseControlWindowImpl_GetMinIdealImageSize(IVideoWindow *iface, LONG *pWidth, LONG *pHeight);
HRESULT WINAPI BaseControlWindowImpl_GetMaxIdealImageSize(IVideoWindow *iface, LONG *pWidth, LONG *pHeight);
HRESULT WINAPI BaseControlWindowImpl_GetRestorePosition(IVideoWindow *iface, LONG *pLeft, LONG *pTop, LONG *pWidth, LONG *pHeight);
HRESULT WINAPI BaseControlWindowImpl_HideCursor(IVideoWindow *iface, LONG HideCursor);
HRESULT WINAPI BaseControlWindowImpl_IsCursorHidden(IVideoWindow *iface, LONG *CursorHidden);
#endif
#ifdef __IBasicVideo_FWD_DEFINED__
#ifdef __amvideo_h__
typedef struct tagBaseControlVideo
{
IBasicVideo IBasicVideo_iface;
BaseDispatch baseDispatch;
BaseFilter* pFilter;
CRITICAL_SECTION* pInterfaceLock;
BasePin* pPin;
const struct BaseControlVideoFuncTable* pFuncsTable;
} BaseControlVideo;
typedef HRESULT (WINAPI *BaseControlVideo_GetSourceRect)(BaseControlVideo* This, RECT *pSourceRect);
typedef HRESULT (WINAPI *BaseControlVideo_GetStaticImage)(BaseControlVideo* This, LONG *pBufferSize, LONG *pDIBImage);
typedef HRESULT (WINAPI *BaseControlVideo_GetTargetRect)(BaseControlVideo* This, RECT *pTargetRect);
typedef VIDEOINFOHEADER* (WINAPI *BaseControlVideo_GetVideoFormat)(BaseControlVideo* This);
typedef HRESULT (WINAPI *BaseControlVideo_IsDefaultSourceRect)(BaseControlVideo* This);
typedef HRESULT (WINAPI *BaseControlVideo_IsDefaultTargetRect)(BaseControlVideo* This);
typedef HRESULT (WINAPI *BaseControlVideo_SetDefaultSourceRect)(BaseControlVideo* This);
typedef HRESULT (WINAPI *BaseControlVideo_SetDefaultTargetRect)(BaseControlVideo* This);
typedef HRESULT (WINAPI *BaseControlVideo_SetSourceRect)(BaseControlVideo* This, RECT *pSourceRect);
typedef HRESULT (WINAPI *BaseControlVideo_SetTargetRect)(BaseControlVideo* This, RECT *pTargetRect);
typedef struct BaseControlVideoFuncTable {
/* Required */
BaseControlVideo_GetSourceRect pfnGetSourceRect;
BaseControlVideo_GetStaticImage pfnGetStaticImage;
BaseControlVideo_GetTargetRect pfnGetTargetRect;
BaseControlVideo_GetVideoFormat pfnGetVideoFormat;
BaseControlVideo_IsDefaultSourceRect pfnIsDefaultSourceRect;
BaseControlVideo_IsDefaultTargetRect pfnIsDefaultTargetRect;
BaseControlVideo_SetDefaultSourceRect pfnSetDefaultSourceRect;
BaseControlVideo_SetDefaultTargetRect pfnSetDefaultTargetRect;
BaseControlVideo_SetSourceRect pfnSetSourceRect;
BaseControlVideo_SetTargetRect pfnSetTargetRect;
} BaseControlVideoFuncTable;
HRESULT WINAPI BaseControlVideo_Init(BaseControlVideo *pControlVideo, const IBasicVideoVtbl *lpVtbl, BaseFilter *owner, CRITICAL_SECTION *lock, BasePin* pPin, const BaseControlVideoFuncTable* pFuncsTable);
HRESULT WINAPI BaseControlVideo_Destroy(BaseControlVideo *pControlVideo);
HRESULT WINAPI BaseControlVideoImpl_GetTypeInfoCount(IBasicVideo *iface, UINT*pctinfo);
HRESULT WINAPI BaseControlVideoImpl_GetTypeInfo(IBasicVideo *iface, UINT iTInfo, LCID lcid, ITypeInfo**ppTInfo);
HRESULT WINAPI BaseControlVideoImpl_GetIDsOfNames(IBasicVideo *iface, REFIID riid, LPOLESTR*rgszNames, UINT cNames, LCID lcid, DISPID*rgDispId);
HRESULT WINAPI BaseControlVideoImpl_Invoke(IBasicVideo *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS*pDispParams, VARIANT*pVarResult, EXCEPINFO*pExepInfo, UINT*puArgErr);
HRESULT WINAPI BaseControlVideoImpl_get_AvgTimePerFrame(IBasicVideo *iface, REFTIME *pAvgTimePerFrame);
HRESULT WINAPI BaseControlVideoImpl_get_BitRate(IBasicVideo *iface, LONG *pBitRate);
HRESULT WINAPI BaseControlVideoImpl_get_BitErrorRate(IBasicVideo *iface, LONG *pBitErrorRate);
HRESULT WINAPI BaseControlVideoImpl_get_VideoWidth(IBasicVideo *iface, LONG *pVideoWidth);
HRESULT WINAPI BaseControlVideoImpl_get_VideoHeight(IBasicVideo *iface, LONG *pVideoHeight);
HRESULT WINAPI BaseControlVideoImpl_put_SourceLeft(IBasicVideo *iface, LONG SourceLeft);
HRESULT WINAPI BaseControlVideoImpl_get_SourceLeft(IBasicVideo *iface, LONG *pSourceLeft);
HRESULT WINAPI BaseControlVideoImpl_put_SourceWidth(IBasicVideo *iface, LONG SourceWidth);
HRESULT WINAPI BaseControlVideoImpl_get_SourceWidth(IBasicVideo *iface, LONG *pSourceWidth);
HRESULT WINAPI BaseControlVideoImpl_put_SourceTop(IBasicVideo *iface, LONG SourceTop);
HRESULT WINAPI BaseControlVideoImpl_get_SourceTop(IBasicVideo *iface, LONG *pSourceTop);
HRESULT WINAPI BaseControlVideoImpl_put_SourceHeight(IBasicVideo *iface, LONG SourceHeight);
HRESULT WINAPI BaseControlVideoImpl_get_SourceHeight(IBasicVideo *iface, LONG *pSourceHeight);
HRESULT WINAPI BaseControlVideoImpl_put_DestinationLeft(IBasicVideo *iface, LONG DestinationLeft);
HRESULT WINAPI BaseControlVideoImpl_get_DestinationLeft(IBasicVideo *iface, LONG *pDestinationLeft);
HRESULT WINAPI BaseControlVideoImpl_put_DestinationWidth(IBasicVideo *iface, LONG DestinationWidth);
HRESULT WINAPI BaseControlVideoImpl_get_DestinationWidth(IBasicVideo *iface, LONG *pDestinationWidth);
HRESULT WINAPI BaseControlVideoImpl_put_DestinationTop(IBasicVideo *iface, LONG DestinationTop);
HRESULT WINAPI BaseControlVideoImpl_get_DestinationTop(IBasicVideo *iface, LONG *pDestinationTop);
HRESULT WINAPI BaseControlVideoImpl_put_DestinationHeight(IBasicVideo *iface, LONG DestinationHeight);
HRESULT WINAPI BaseControlVideoImpl_get_DestinationHeight(IBasicVideo *iface, LONG *pDestinationHeight);
HRESULT WINAPI BaseControlVideoImpl_SetSourcePosition(IBasicVideo *iface, LONG Left, LONG Top, LONG Width, LONG Height);
HRESULT WINAPI BaseControlVideoImpl_GetSourcePosition(IBasicVideo *iface, LONG *pLeft, LONG *pTop, LONG *pWidth, LONG *pHeight);
HRESULT WINAPI BaseControlVideoImpl_SetDefaultSourcePosition(IBasicVideo *iface);
HRESULT WINAPI BaseControlVideoImpl_SetDestinationPosition(IBasicVideo *iface, LONG Left, LONG Top, LONG Width, LONG Height);
HRESULT WINAPI BaseControlVideoImpl_GetDestinationPosition(IBasicVideo *iface, LONG *pLeft, LONG *pTop, LONG *pWidth, LONG *pHeight);
HRESULT WINAPI BaseControlVideoImpl_SetDefaultDestinationPosition(IBasicVideo *iface);
HRESULT WINAPI BaseControlVideoImpl_GetVideoSize(IBasicVideo *iface, LONG *pWidth, LONG *pHeight);
HRESULT WINAPI BaseControlVideoImpl_GetVideoPaletteEntries(IBasicVideo *iface, LONG StartIndex, LONG Entries, LONG *pRetrieved, LONG *pPalette);
HRESULT WINAPI BaseControlVideoImpl_GetCurrentImage(IBasicVideo *iface, LONG *pBufferSize, LONG *pDIBImage);
HRESULT WINAPI BaseControlVideoImpl_IsUsingDefaultSource(IBasicVideo *iface);
HRESULT WINAPI BaseControlVideoImpl_IsUsingDefaultDestination(IBasicVideo *iface);
#endif
#endif
/* BaseRenderer Filter */
typedef struct BaseRendererTag
{
BaseFilter filter;
BaseInputPin *pInputPin;
IUnknown *pPosition;
CRITICAL_SECTION csRenderLock;
HANDLE evComplete;
HANDLE ThreadSignal;
HANDLE RenderEvent;
IMediaSample *pMediaSample;
IQualityControl *pQSink;
struct QualityControlImpl *qcimpl;
const struct BaseRendererFuncTable * pFuncsTable;
} BaseRenderer;
typedef HRESULT (WINAPI *BaseRenderer_CheckMediaType)(BaseRenderer *This, const AM_MEDIA_TYPE *pmt);
typedef HRESULT (WINAPI *BaseRenderer_DoRenderSample)(BaseRenderer *This, IMediaSample *pMediaSample);
typedef VOID (WINAPI *BaseRenderer_OnReceiveFirstSample)(BaseRenderer *This, IMediaSample *pMediaSample);
typedef VOID (WINAPI *BaseRenderer_OnRenderEnd)(BaseRenderer *This, IMediaSample *pMediaSample);
typedef VOID (WINAPI *BaseRenderer_OnRenderStart)(BaseRenderer *This, IMediaSample *pMediaSample);
typedef VOID (WINAPI *BaseRenderer_OnStartStreaming)(BaseRenderer *This);
typedef VOID (WINAPI *BaseRenderer_OnStopStreaming)(BaseRenderer *This);
typedef VOID (WINAPI *BaseRenderer_OnWaitEnd)(BaseRenderer *This);
typedef VOID (WINAPI *BaseRenderer_OnWaitStart)(BaseRenderer *This);
typedef VOID (WINAPI *BaseRenderer_PrepareRender)(BaseRenderer *This);
typedef HRESULT (WINAPI *BaseRenderer_ShouldDrawSampleNow)(BaseRenderer *This, IMediaSample *pMediaSample, REFERENCE_TIME *pStartTime, REFERENCE_TIME *pEndTime);
typedef HRESULT (WINAPI *BaseRenderer_PrepareReceive)(BaseRenderer *This, IMediaSample *pMediaSample);
typedef HRESULT (WINAPI *BaseRenderer_EndOfStream)(BaseRenderer *This);
typedef HRESULT (WINAPI *BaseRenderer_BeginFlush) (BaseRenderer *This);
typedef HRESULT (WINAPI *BaseRenderer_EndFlush) (BaseRenderer *This);
typedef HRESULT (WINAPI *BaseRenderer_BreakConnect) (BaseRenderer *This);
typedef HRESULT (WINAPI *BaseRenderer_CompleteConnect) (BaseRenderer *This, IPin *pReceivePin);
typedef struct BaseRendererFuncTable {
/* Required */
BaseRenderer_CheckMediaType pfnCheckMediaType;
BaseRenderer_DoRenderSample pfnDoRenderSample;
/* Optional, Data Handlers */
BaseRenderer_OnReceiveFirstSample pfnOnReceiveFirstSample;
BaseRenderer_OnRenderEnd pfnOnRenderEnd;
BaseRenderer_OnRenderStart pfnOnRenderStart;
BaseRenderer_OnStartStreaming pfnOnStartStreaming;
BaseRenderer_OnStopStreaming pfnOnStopStreaming;
BaseRenderer_OnWaitEnd pfnOnWaitEnd;
BaseRenderer_OnWaitStart pfnOnWaitStart;
BaseRenderer_PrepareRender pfnPrepareRender;
BaseRenderer_ShouldDrawSampleNow pfnShouldDrawSampleNow;
BaseRenderer_PrepareReceive pfnPrepareReceive;
/* Optional, Input Pin */
BaseRenderer_CompleteConnect pfnCompleteConnect;
BaseRenderer_BreakConnect pfnBreakConnect;
BaseRenderer_EndOfStream pfnEndOfStream;
BaseRenderer_BeginFlush pfnBeginFlush;
BaseRenderer_EndFlush pfnEndFlush;
} BaseRendererFuncTable;
HRESULT WINAPI BaseRendererImpl_QueryInterface(IBaseFilter * iface, REFIID riid, LPVOID * ppv);
ULONG WINAPI BaseRendererImpl_Release(IBaseFilter * iface);
HRESULT WINAPI BaseRendererImpl_Receive(BaseRenderer *This, IMediaSample * pSample);
HRESULT WINAPI BaseRendererImpl_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin);
HRESULT WINAPI BaseRendererImpl_Stop(IBaseFilter * iface);
HRESULT WINAPI BaseRendererImpl_Run(IBaseFilter * iface, REFERENCE_TIME tStart);
HRESULT WINAPI BaseRendererImpl_Pause(IBaseFilter * iface);
HRESULT WINAPI BaseRendererImpl_SetSyncSource(IBaseFilter *iface, IReferenceClock *clock);
HRESULT WINAPI BaseRendererImpl_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState);
HRESULT WINAPI BaseRendererImpl_EndOfStream(BaseRenderer* iface);
HRESULT WINAPI BaseRendererImpl_BeginFlush(BaseRenderer* iface);
HRESULT WINAPI BaseRendererImpl_EndFlush(BaseRenderer* iface);
HRESULT WINAPI BaseRendererImpl_ClearPendingSample(BaseRenderer *iface);
HRESULT WINAPI BaseRenderer_Init(BaseRenderer *This, const IBaseFilterVtbl *Vtbl, IUnknown *pUnkOuter, const CLSID *pClsid, DWORD_PTR DebugInfo, const BaseRendererFuncTable* pBaseFuncsTable);
#ifdef __IBasicAudio_FWD_DEFINED__
typedef struct tagBasicAudio
{
IBasicAudio IBasicAudio_iface;
BaseDispatch baseDispatch;
} BasicAudio;
HRESULT WINAPI BasicAudio_Init(BasicAudio *This, const IBasicAudioVtbl *Vtbl);
HRESULT WINAPI BasicAudio_Destroy(BasicAudio *pBasicAudio);
HRESULT WINAPI BasicAudioImpl_GetTypeInfoCount(IBasicAudio *iface, UINT*pctinfo);
HRESULT WINAPI BasicAudioImpl_GetTypeInfo(IBasicAudio *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo);
HRESULT WINAPI BasicAudioImpl_GetIDsOfNames(IBasicAudio *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId);
HRESULT WINAPI BasicAudioImpl_Invoke(IBasicAudio *iface, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExepInfo, UINT *puArgErr);
#endif
/* Dll Functions */
BOOL WINAPI STRMBASE_DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv);
HRESULT WINAPI STRMBASE_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv);
HRESULT WINAPI STRMBASE_DllCanUnloadNow(void);

View file

@ -10,4 +10,5 @@ add_subdirectory(libsamplerate)
add_subdirectory(libwine)
add_subdirectory(libxml2)
# add_subdirectory(stlport) FIXME: Add proper STL support
add_subdirectory(strmbase)
add_subdirectory(zlib)

View file

@ -0,0 +1,23 @@
include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine)
add_definitions(-D__WINESRC__)
list(APPEND SOURCE
audio.c
dispatch.c
dllfunc.c
enumpins.c
filter.c
mediatype.c
outputqueue.c
pin.c
pospass.c
qualitycontrol.c
renderer.c
seeking.c
transform.c
video.c
window.c)
add_library(strmbase ${SOURCE})
add_dependencies(strmbase psdk dxsdk)

84
reactos/lib/3rdparty/strmbase/audio.c vendored Normal file
View file

@ -0,0 +1,84 @@
/*
* Generic Implementation of strmbase audio classes
*
* Copyright 2012 Aric Stewart, CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#include <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;
}

View file

@ -0,0 +1,79 @@
/*
* Generic Implementation of IDispatch for strmbase classes
*
* Copyright 2012 Aric Stewart, CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#include "dshow.h"
#include "wine/unicode.h"
#include "wine/strmbase.h"
#include "uuids.h"
#include "vfwmsgs.h"
#include <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;
}

469
reactos/lib/3rdparty/strmbase/dllfunc.c vendored Normal file
View file

@ -0,0 +1,469 @@
/*
* Strmbase DLL functions
*
* Copyright (C) 2005 Rolf Kalbermatter
* Copyright (C) 2010 Aric Stewart, CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include <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;
}

View file

@ -2,6 +2,7 @@
* Implementation of IEnumPins Interface
*
* Copyright 2003 Robert Shearman
* Copyright 2010 Aric Stewart, CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -18,25 +19,34 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "quartz_private.h"
#define COBJMACROS
#include <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;
@ -49,15 +59,16 @@ HRESULT IEnumPinsImpl_Construct(IEnumPins ** ppEnum, FNOBTAINPIN receive_pin, IB
*ppEnum = NULL;
return E_OUTOFMEMORY;
}
pEnumPins->lpVtbl = &IEnumPinsImpl_Vtbl;
pEnumPins->IEnumPins_iface.lpVtbl = &IEnumPinsImpl_Vtbl;
pEnumPins->refCount = 1;
pEnumPins->uIndex = 0;
pEnumPins->receive_pin = receive_pin;
pEnumPins->receive_pincount = receive_pincount;
pEnumPins->receive_version = receive_version;
pEnumPins->base = base;
IBaseFilter_AddRef(base);
*ppEnum = (IEnumPins *)(&pEnumPins->lpVtbl);
receive_pin(base, ~0, NULL, &pEnumPins->synctime);
IBaseFilter_AddRef(&base->IBaseFilter_iface);
*ppEnum = &pEnumPins->IEnumPins_iface;
pEnumPins->Version = receive_version(base);
TRACE("Created new enumerator (%p)\n", *ppEnum);
return S_OK;
@ -65,7 +76,7 @@ HRESULT IEnumPinsImpl_Construct(IEnumPins ** ppEnum, FNOBTAINPIN receive_pin, IB
static HRESULT WINAPI IEnumPinsImpl_QueryInterface(IEnumPins * iface, REFIID riid, LPVOID * ppv)
{
TRACE("(%s, %p)\n", qzdebugstr_guid(riid), ppv);
TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
*ppv = NULL;
@ -80,14 +91,14 @@ static HRESULT WINAPI IEnumPinsImpl_QueryInterface(IEnumPins * iface, REFIID rii
return S_OK;
}
FIXME("No interface for %s!\n", qzdebugstr_guid(riid));
FIXME("No interface for %s!\n", debugstr_guid(riid));
return E_NOINTERFACE;
}
static ULONG WINAPI IEnumPinsImpl_AddRef(IEnumPins * iface)
{
IEnumPinsImpl *This = (IEnumPinsImpl *)iface;
IEnumPinsImpl *This = impl_from_IEnumPins(iface);
ULONG refCount = InterlockedIncrement(&This->refCount);
TRACE("(%p)->() AddRef from %d\n", This, refCount - 1);
@ -97,14 +108,14 @@ static ULONG WINAPI IEnumPinsImpl_AddRef(IEnumPins * iface)
static ULONG WINAPI IEnumPinsImpl_Release(IEnumPins * iface)
{
IEnumPinsImpl *This = (IEnumPinsImpl *)iface;
IEnumPinsImpl *This = impl_from_IEnumPins(iface);
ULONG refCount = InterlockedDecrement(&This->refCount);
TRACE("(%p)->() Release from %d\n", This, refCount + 1);
if (!refCount)
{
IBaseFilter_Release(This->base);
IBaseFilter_Release(&This->base->IBaseFilter_iface);
CoTaskMemFree(This);
return 0;
}
@ -114,8 +125,7 @@ static ULONG WINAPI IEnumPinsImpl_Release(IEnumPins * iface)
static HRESULT WINAPI IEnumPinsImpl_Next(IEnumPins * iface, ULONG cPins, IPin ** ppPins, ULONG * pcFetched)
{
IEnumPinsImpl *This = (IEnumPinsImpl *)iface;
DWORD synctime = This->synctime;
IEnumPinsImpl *This = impl_from_IEnumPins(iface);
HRESULT hr = S_OK;
ULONG i = 0;
@ -130,20 +140,21 @@ static HRESULT WINAPI IEnumPinsImpl_Next(IEnumPins * iface, ULONG cPins, IPin **
if (pcFetched)
*pcFetched = 0;
if (This->Version != This->receive_version(This->base))
return VFW_E_ENUM_OUT_OF_SYNC;
while (i < cPins && hr == S_OK)
{
hr = This->receive_pin(This->base, This->uIndex + i, &ppPins[i], &synctime);
IPin *pin;
pin = This->receive_pin(This->base, This->uIndex + i);
if (hr == S_OK)
++i;
if (synctime != This->synctime)
break;
if (!pin)
break;
else
ppPins[i] = pin;
++i;
}
if (!i && synctime != This->synctime)
return VFW_E_ENUM_OUT_OF_SYNC;
if (pcFetched)
*pcFetched = i;
This->uIndex += i;
@ -155,32 +166,26 @@ static HRESULT WINAPI IEnumPinsImpl_Next(IEnumPins * iface, ULONG cPins, IPin **
static HRESULT WINAPI IEnumPinsImpl_Skip(IEnumPins * iface, ULONG cPins)
{
IEnumPinsImpl *This = (IEnumPinsImpl *)iface;
DWORD synctime = This->synctime;
HRESULT hr;
IPin *pin = NULL;
IEnumPinsImpl *This = impl_from_IEnumPins(iface);
TRACE("(%u)\n", cPins);
hr = This->receive_pin(This->base, This->uIndex + cPins, &pin, &synctime);
if (pin)
IPin_Release(pin);
if (synctime != This->synctime)
if (This->Version != This->receive_version(This->base))
return VFW_E_ENUM_OUT_OF_SYNC;
if (hr == S_OK)
This->uIndex += cPins;
if (This->receive_pincount(This->base) >= This->uIndex + cPins)
return S_FALSE;
return hr;
This->uIndex += cPins;
return S_OK;
}
static HRESULT WINAPI IEnumPinsImpl_Reset(IEnumPins * iface)
{
IEnumPinsImpl *This = (IEnumPinsImpl *)iface;
IEnumPinsImpl *This = impl_from_IEnumPins(iface);
TRACE("IEnumPinsImpl::Reset()\n");
This->receive_pin(This->base, ~0, NULL, &This->synctime);
This->Version = This->receive_version(This->base);
This->uIndex = 0;
return S_OK;
@ -189,11 +194,11 @@ static HRESULT WINAPI IEnumPinsImpl_Reset(IEnumPins * iface)
static HRESULT WINAPI IEnumPinsImpl_Clone(IEnumPins * iface, IEnumPins ** ppEnum)
{
HRESULT hr;
IEnumPinsImpl *This = (IEnumPinsImpl *)iface;
IEnumPinsImpl *This = impl_from_IEnumPins(iface);
TRACE("(%p)\n", ppEnum);
hr = IEnumPinsImpl_Construct(ppEnum, This->receive_pin, This->base);
hr = EnumPins_Construct(This->base, This->receive_pin, This->receive_pincount, This->receive_version, ppEnum);
if (FAILED(hr))
return hr;
return IEnumPins_Skip(*ppEnum, This->uIndex);

228
reactos/lib/3rdparty/strmbase/filter.c vendored Normal file
View file

@ -0,0 +1,228 @@
/*
* Generic Implementation of IBaseFilter Interface
*
* Copyright 2010 Aric Stewart, CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#include "dshow.h"
#include "wine/debug.h"
#include "wine/unicode.h"
#include "wine/strmbase.h"
#include "uuids.h"
#include <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;
}

View file

@ -0,0 +1,307 @@
/*
* Implementation of MedaType utility functions
*
* Copyright 2003 Robert Shearman
* Copyright 2010 Aric Stewart, CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <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
};

View file

@ -0,0 +1,310 @@
/*
* Generic Implementation of COutputQueue
*
* Copyright 2011 Aric Stewart, CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#include "dshow.h"
#include "wine/debug.h"
#include "wine/unicode.h"
#include "wine/list.h"
#include "wine/strmbase.h"
#include "uuids.h"
#include "vfwmsgs.h"
#include <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;
}

1269
reactos/lib/3rdparty/strmbase/pin.c vendored Normal file

File diff suppressed because it is too large Load diff

938
reactos/lib/3rdparty/strmbase/pospass.c vendored Normal file
View file

@ -0,0 +1,938 @@
/*
* Filter Seeking and Control Interfaces
*
* Copyright 2003 Robert Shearman
* Copyright 2012 Aric Stewart, CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
/* FIXME: critical sections */
#define COBJMACROS
#include "dshow.h"
#include "uuids.h"
#include "wine/debug.h"
#include "wine/strmbase.h"
#include <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
};

View file

@ -0,0 +1,318 @@
/*
* Quality Control Interfaces
*
* Copyright 2010 Maarten Lankhorst for CodeWeavers
*
* rendering qos functions based on, the original can be found at
* gstreamer/libs/gst/base/gstbasesink.c which has copyright notice:
*
* Copyright (C) 2005-2007 Wim Taymans <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);
}

614
reactos/lib/3rdparty/strmbase/renderer.c vendored Normal file
View file

@ -0,0 +1,614 @@
/*
* Generic Implementation of strmbase Base Renderer classes
*
* Copyright 2012 Aric Stewart, CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#include "dshow.h"
#include "wine/debug.h"
#include "wine/unicode.h"
#include "wine/strmbase.h"
#include "uuids.h"
#include "vfwmsgs.h"
#include "strmbase_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(strmbase);
static const WCHAR wcsInputPinName[] = {'i','n','p','u','t',' ','p','i','n',0};
static const WCHAR wcsAltInputPinName[] = {'I','n',0};
static inline BaseInputPin *impl_BaseInputPin_from_IPin( IPin *iface )
{
return CONTAINING_RECORD(iface, BaseInputPin, pin.IPin_iface);
}
static inline BaseRenderer *impl_from_IBaseFilter(IBaseFilter *iface)
{
return CONTAINING_RECORD(iface, BaseRenderer, filter.IBaseFilter_iface);
}
static inline BaseRenderer *impl_from_BaseFilter(BaseFilter *iface)
{
return CONTAINING_RECORD(iface, BaseRenderer, filter);
}
static const IQualityControlVtbl Renderer_QualityControl_Vtbl = {
QualityControlImpl_QueryInterface,
QualityControlImpl_AddRef,
QualityControlImpl_Release,
QualityControlImpl_Notify,
QualityControlImpl_SetSink
};
static HRESULT WINAPI BaseRenderer_InputPin_ReceiveConnection(IPin * iface, IPin * pReceivePin, const AM_MEDIA_TYPE * pmt)
{
BaseInputPin *This = impl_BaseInputPin_from_IPin(iface);
BaseRenderer *renderer = impl_from_IBaseFilter(This->pin.pinInfo.pFilter);
HRESULT hr = S_OK;
TRACE("(%p/%p)->(%p, %p)\n", This, renderer, pReceivePin, pmt);
EnterCriticalSection(This->pin.pCritSec);
hr = BaseInputPinImpl_ReceiveConnection(iface, pReceivePin, pmt);
if (SUCCEEDED(hr))
{
if (renderer->pFuncsTable->pfnCompleteConnect)
hr = renderer->pFuncsTable->pfnCompleteConnect(renderer, pReceivePin);
}
LeaveCriticalSection(This->pin.pCritSec);
return hr;
}
static HRESULT WINAPI BaseRenderer_InputPin_Disconnect(IPin * iface)
{
BaseInputPin *This = impl_BaseInputPin_from_IPin(iface);
BaseRenderer *renderer = impl_from_IBaseFilter(This->pin.pinInfo.pFilter);
HRESULT hr;
TRACE("(%p/%p)\n", This, renderer);
EnterCriticalSection(This->pin.pCritSec);
hr = BasePinImpl_Disconnect(iface);
if (SUCCEEDED(hr))
{
if (renderer->pFuncsTable->pfnBreakConnect)
hr = renderer->pFuncsTable->pfnBreakConnect(renderer);
}
BaseRendererImpl_ClearPendingSample(renderer);
LeaveCriticalSection(This->pin.pCritSec);
return hr;
}
static HRESULT WINAPI BaseRenderer_InputPin_EndOfStream(IPin * iface)
{
HRESULT hr = S_OK;
BaseInputPin* This = impl_BaseInputPin_from_IPin(iface);
BaseRenderer *pFilter = impl_from_IBaseFilter(This->pin.pinInfo.pFilter);
TRACE("(%p/%p)->()\n", This, pFilter);
EnterCriticalSection(&pFilter->filter.csFilter);
EnterCriticalSection(&pFilter->csRenderLock);
hr = BaseInputPinImpl_EndOfStream(iface);
EnterCriticalSection(This->pin.pCritSec);
if (SUCCEEDED(hr))
{
if (pFilter->pFuncsTable->pfnEndOfStream)
hr = pFilter->pFuncsTable->pfnEndOfStream(pFilter);
else
hr = BaseRendererImpl_EndOfStream(pFilter);
}
LeaveCriticalSection(This->pin.pCritSec);
LeaveCriticalSection(&pFilter->csRenderLock);
LeaveCriticalSection(&pFilter->filter.csFilter);
return hr;
}
static HRESULT WINAPI BaseRenderer_InputPin_BeginFlush(IPin * iface)
{
BaseInputPin* This = impl_BaseInputPin_from_IPin(iface);
BaseRenderer *pFilter = impl_from_IBaseFilter(This->pin.pinInfo.pFilter);
HRESULT hr = S_OK;
TRACE("(%p/%p)->()\n", This, iface);
EnterCriticalSection(&pFilter->filter.csFilter);
EnterCriticalSection(&pFilter->csRenderLock);
EnterCriticalSection(This->pin.pCritSec);
hr = BaseInputPinImpl_BeginFlush(iface);
if (SUCCEEDED(hr))
{
if (pFilter->pFuncsTable->pfnBeginFlush)
hr = pFilter->pFuncsTable->pfnBeginFlush(pFilter);
else
hr = BaseRendererImpl_BeginFlush(pFilter);
}
LeaveCriticalSection(This->pin.pCritSec);
LeaveCriticalSection(&pFilter->filter.csFilter);
LeaveCriticalSection(&pFilter->csRenderLock);
return hr;
}
static HRESULT WINAPI BaseRenderer_InputPin_EndFlush(IPin * iface)
{
BaseInputPin* This = impl_BaseInputPin_from_IPin(iface);
BaseRenderer *pFilter = impl_from_IBaseFilter(This->pin.pinInfo.pFilter);
HRESULT hr = S_OK;
TRACE("(%p/%p)->()\n", This, pFilter);
EnterCriticalSection(&pFilter->filter.csFilter);
EnterCriticalSection(&pFilter->csRenderLock);
EnterCriticalSection(This->pin.pCritSec);
hr = BaseInputPinImpl_EndFlush(iface);
if (SUCCEEDED(hr))
{
if (pFilter->pFuncsTable->pfnEndFlush)
hr = pFilter->pFuncsTable->pfnEndFlush(pFilter);
else
hr = BaseRendererImpl_EndFlush(pFilter);
}
LeaveCriticalSection(This->pin.pCritSec);
LeaveCriticalSection(&pFilter->csRenderLock);
LeaveCriticalSection(&pFilter->filter.csFilter);
return hr;
}
static const IPinVtbl BaseRenderer_InputPin_Vtbl =
{
BaseInputPinImpl_QueryInterface,
BasePinImpl_AddRef,
BaseInputPinImpl_Release,
BaseInputPinImpl_Connect,
BaseRenderer_InputPin_ReceiveConnection,
BaseRenderer_InputPin_Disconnect,
BasePinImpl_ConnectedTo,
BasePinImpl_ConnectionMediaType,
BasePinImpl_QueryPinInfo,
BasePinImpl_QueryDirection,
BasePinImpl_QueryId,
BaseInputPinImpl_QueryAccept,
BasePinImpl_EnumMediaTypes,
BasePinImpl_QueryInternalConnections,
BaseRenderer_InputPin_EndOfStream,
BaseRenderer_InputPin_BeginFlush,
BaseRenderer_InputPin_EndFlush,
BaseInputPinImpl_NewSegment
};
static IPin* WINAPI BaseRenderer_GetPin(BaseFilter *iface, int pos)
{
BaseRenderer *This = impl_from_BaseFilter(iface);
if (pos >= 1 || pos < 0)
return NULL;
IPin_AddRef(&This->pInputPin->pin.IPin_iface);
return &This->pInputPin->pin.IPin_iface;
}
static LONG WINAPI BaseRenderer_GetPinCount(BaseFilter *iface)
{
return 1;
}
static HRESULT WINAPI BaseRenderer_Input_CheckMediaType(BasePin *pin, const AM_MEDIA_TYPE * pmt)
{
BaseRenderer *This = impl_from_IBaseFilter(pin->pinInfo.pFilter);
return This->pFuncsTable->pfnCheckMediaType(This, pmt);
}
static HRESULT WINAPI BaseRenderer_Receive(BaseInputPin *pin, IMediaSample * pSample)
{
BaseRenderer *This = impl_from_IBaseFilter(pin->pin.pinInfo.pFilter);
return BaseRendererImpl_Receive(This, pSample);
}
static const BaseFilterFuncTable RendererBaseFilterFuncTable = {
BaseRenderer_GetPin,
BaseRenderer_GetPinCount
};
static const BasePinFuncTable input_BaseFuncTable = {
BaseRenderer_Input_CheckMediaType,
NULL,
BasePinImpl_GetMediaTypeVersion,
BasePinImpl_GetMediaType
};
static const BaseInputPinFuncTable input_BaseInputFuncTable = {
BaseRenderer_Receive
};
HRESULT WINAPI BaseRenderer_Init(BaseRenderer * This, const IBaseFilterVtbl *Vtbl, IUnknown *pUnkOuter, const CLSID *pClsid, DWORD_PTR DebugInfo, const BaseRendererFuncTable* pBaseFuncsTable)
{
PIN_INFO piInput;
HRESULT hr;
BaseFilter_Init(&This->filter, Vtbl, pClsid, DebugInfo, &RendererBaseFilterFuncTable);
This->pFuncsTable = pBaseFuncsTable;
/* construct input pin */
piInput.dir = PINDIR_INPUT;
piInput.pFilter = &This->filter.IBaseFilter_iface;
lstrcpynW(piInput.achName, wcsInputPinName, sizeof(piInput.achName) / sizeof(piInput.achName[0]));
hr = BaseInputPin_Construct(&BaseRenderer_InputPin_Vtbl, &piInput, &input_BaseFuncTable, &input_BaseInputFuncTable, &This->filter.csFilter, NULL, (IPin **)&This->pInputPin);
if (SUCCEEDED(hr))
{
hr = CreatePosPassThru(pUnkOuter ? pUnkOuter: (IUnknown*)This, TRUE, &This->pInputPin->pin.IPin_iface, &This->pPosition);
if (FAILED(hr))
return hr;
InitializeCriticalSection(&This->csRenderLock);
This->csRenderLock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__": BaseRenderer.csRenderLock");
This->evComplete = CreateEventW(NULL, TRUE, TRUE, NULL);
This->ThreadSignal = CreateEventW(NULL, TRUE, TRUE, NULL);
This->RenderEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
This->pMediaSample = NULL;
QualityControlImpl_Create(&This->pInputPin->pin.IPin_iface, &This->filter.IBaseFilter_iface, &This->qcimpl);
This->qcimpl->IQualityControl_iface.lpVtbl = &Renderer_QualityControl_Vtbl;
}
return hr;
}
HRESULT WINAPI BaseRendererImpl_QueryInterface(IBaseFilter* iface, REFIID riid, LPVOID * ppv)
{
BaseRenderer *This = impl_from_IBaseFilter(iface);
if (IsEqualIID(riid, &IID_IMediaSeeking) || IsEqualIID(riid, &IID_IMediaPosition))
return IUnknown_QueryInterface(This->pPosition, riid, ppv);
else if (IsEqualIID(riid, &IID_IQualityControl))
{
*ppv = &This->qcimpl->IQualityControl_iface;
IUnknown_AddRef((IUnknown *)(*ppv));
return S_OK;
}
else
return BaseFilterImpl_QueryInterface(iface, riid, ppv);
}
ULONG WINAPI BaseRendererImpl_Release(IBaseFilter* iface)
{
BaseRenderer *This = impl_from_IBaseFilter(iface);
ULONG refCount = BaseFilterImpl_Release(iface);
if (!refCount)
{
IPin *pConnectedTo;
if (SUCCEEDED(IPin_ConnectedTo(&This->pInputPin->pin.IPin_iface, &pConnectedTo)))
{
IPin_Disconnect(pConnectedTo);
IPin_Release(pConnectedTo);
}
IPin_Disconnect(&This->pInputPin->pin.IPin_iface);
IPin_Release(&This->pInputPin->pin.IPin_iface);
if (This->pPosition)
IUnknown_Release(This->pPosition);
This->csRenderLock.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&This->csRenderLock);
BaseRendererImpl_ClearPendingSample(This);
CloseHandle(This->evComplete);
CloseHandle(This->ThreadSignal);
CloseHandle(This->RenderEvent);
QualityControlImpl_Destroy(This->qcimpl);
}
return refCount;
}
HRESULT WINAPI BaseRendererImpl_Receive(BaseRenderer *This, IMediaSample * pSample)
{
HRESULT hr = S_OK;
REFERENCE_TIME start, stop;
AM_MEDIA_TYPE *pmt;
TRACE("(%p)->%p\n", This, pSample);
if (This->pInputPin->end_of_stream || This->pInputPin->flushing)
return S_FALSE;
if (This->filter.state == State_Stopped)
return VFW_E_WRONG_STATE;
if (IMediaSample_GetMediaType(pSample, &pmt) == S_OK)
{
if (FAILED(This->pFuncsTable->pfnCheckMediaType(This, pmt)))
{
return VFW_E_TYPE_NOT_ACCEPTED;
}
}
This->pMediaSample = pSample;
IMediaSample_AddRef(pSample);
if (This->pFuncsTable->pfnPrepareReceive)
hr = This->pFuncsTable->pfnPrepareReceive(This, pSample);
if (FAILED(hr))
{
if (hr == VFW_E_SAMPLE_REJECTED)
return S_OK;
else
return hr;
}
if (This->pFuncsTable->pfnPrepareRender)
This->pFuncsTable->pfnPrepareRender(This);
EnterCriticalSection(&This->csRenderLock);
if ( This->filter.state == State_Paused )
{
if (This->pFuncsTable->pfnOnReceiveFirstSample)
This->pFuncsTable->pfnOnReceiveFirstSample(This, pSample);
SetEvent(This->evComplete);
}
/* Wait for render Time */
if (SUCCEEDED(IMediaSample_GetTime(pSample, &start, &stop)))
{
hr = S_FALSE;
RendererPosPassThru_RegisterMediaTime(This->pPosition, start);
if (This->pFuncsTable->pfnShouldDrawSampleNow)
hr = This->pFuncsTable->pfnShouldDrawSampleNow(This, pSample, &start, &stop);
if (hr == S_OK)
;/* Do not wait: drop through */
else if (hr == S_FALSE)
{
if (This->pFuncsTable->pfnOnWaitStart)
This->pFuncsTable->pfnOnWaitStart(This);
LeaveCriticalSection(&This->csRenderLock);
hr = QualityControlRender_WaitFor(This->qcimpl, pSample, This->RenderEvent);
EnterCriticalSection(&This->csRenderLock);
if (This->pFuncsTable->pfnOnWaitEnd)
This->pFuncsTable->pfnOnWaitEnd(This);
}
else
{
LeaveCriticalSection(&This->csRenderLock);
/* Drop Sample */
return S_OK;
}
}
if (SUCCEEDED(hr))
{
QualityControlRender_BeginRender(This->qcimpl);
hr = This->pFuncsTable->pfnDoRenderSample(This, pSample);
QualityControlRender_EndRender(This->qcimpl);
}
QualityControlRender_DoQOS(This->qcimpl);
BaseRendererImpl_ClearPendingSample(This);
LeaveCriticalSection(&This->csRenderLock);
return hr;
}
HRESULT WINAPI BaseRendererImpl_FindPin(IBaseFilter * iface, LPCWSTR Id, IPin **ppPin)
{
BaseRenderer *This = impl_from_IBaseFilter(iface);
TRACE("(%p)->(%s,%p)\n", This, debugstr_w(Id), ppPin);
if (!Id || !ppPin)
return E_POINTER;
if (!lstrcmpiW(Id,wcsInputPinName) || !lstrcmpiW(Id,wcsAltInputPinName))
{
*ppPin = &This->pInputPin->pin.IPin_iface;
IPin_AddRef(*ppPin);
return S_OK;
}
*ppPin = NULL;
return VFW_E_NOT_FOUND;
}
HRESULT WINAPI BaseRendererImpl_Stop(IBaseFilter * iface)
{
BaseRenderer *This = impl_from_IBaseFilter(iface);
TRACE("(%p)->()\n", This);
EnterCriticalSection(&This->csRenderLock);
{
RendererPosPassThru_ResetMediaTime(This->pPosition);
if (This->pFuncsTable->pfnOnStopStreaming)
This->pFuncsTable->pfnOnStopStreaming(This);
This->filter.state = State_Stopped;
SetEvent(This->evComplete);
SetEvent(This->ThreadSignal);
SetEvent(This->RenderEvent);
}
LeaveCriticalSection(&This->csRenderLock);
return S_OK;
}
HRESULT WINAPI BaseRendererImpl_Run(IBaseFilter * iface, REFERENCE_TIME tStart)
{
HRESULT hr = S_OK;
BaseRenderer *This = impl_from_IBaseFilter(iface);
TRACE("(%p)->(%s)\n", This, wine_dbgstr_longlong(tStart));
EnterCriticalSection(&This->csRenderLock);
This->filter.rtStreamStart = tStart;
if (This->filter.state == State_Running)
goto out;
SetEvent(This->evComplete);
ResetEvent(This->ThreadSignal);
if (This->pInputPin->pin.pConnectedTo)
{
This->pInputPin->end_of_stream = 0;
}
else if (This->filter.filterInfo.pGraph)
{
IMediaEventSink *pEventSink;
hr = IFilterGraph_QueryInterface(This->filter.filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink);
if (SUCCEEDED(hr))
{
hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, (LONG_PTR)This);
IMediaEventSink_Release(pEventSink);
}
hr = S_OK;
}
if (SUCCEEDED(hr))
{
QualityControlRender_Start(This->qcimpl, This->filter.rtStreamStart);
if (This->pFuncsTable->pfnOnStartStreaming)
This->pFuncsTable->pfnOnStartStreaming(This);
if (This->filter.state == State_Stopped)
BaseRendererImpl_ClearPendingSample(This);
SetEvent(This->RenderEvent);
This->filter.state = State_Running;
}
out:
LeaveCriticalSection(&This->csRenderLock);
return hr;
}
HRESULT WINAPI BaseRendererImpl_Pause(IBaseFilter * iface)
{
BaseRenderer *This = impl_from_IBaseFilter(iface);
TRACE("(%p)->()\n", This);
EnterCriticalSection(&This->csRenderLock);
{
if (This->filter.state != State_Paused)
{
if (This->filter.state == State_Stopped)
{
if (This->pInputPin->pin.pConnectedTo)
ResetEvent(This->evComplete);
This->pInputPin->end_of_stream = 0;
}
else if (This->pFuncsTable->pfnOnStopStreaming)
This->pFuncsTable->pfnOnStopStreaming(This);
if (This->filter.state == State_Stopped)
BaseRendererImpl_ClearPendingSample(This);
ResetEvent(This->RenderEvent);
This->filter.state = State_Paused;
}
}
ResetEvent(This->ThreadSignal);
LeaveCriticalSection(&This->csRenderLock);
return S_OK;
}
HRESULT WINAPI BaseRendererImpl_SetSyncSource(IBaseFilter *iface, IReferenceClock *clock)
{
BaseRenderer *This = impl_from_IBaseFilter(iface);
HRESULT hr;
EnterCriticalSection(&This->filter.csFilter);
QualityControlRender_SetClock(This->qcimpl, clock);
hr = BaseFilterImpl_SetSyncSource(iface, clock);
LeaveCriticalSection(&This->filter.csFilter);
return hr;
}
HRESULT WINAPI BaseRendererImpl_GetState(IBaseFilter * iface, DWORD dwMilliSecsTimeout, FILTER_STATE *pState)
{
HRESULT hr;
BaseRenderer *This = impl_from_IBaseFilter(iface);
TRACE("(%p)->(%d, %p)\n", This, dwMilliSecsTimeout, pState);
if (WaitForSingleObject(This->evComplete, dwMilliSecsTimeout) == WAIT_TIMEOUT)
hr = VFW_S_STATE_INTERMEDIATE;
else
hr = S_OK;
BaseFilterImpl_GetState(iface, dwMilliSecsTimeout, pState);
return hr;
}
HRESULT WINAPI BaseRendererImpl_EndOfStream(BaseRenderer* iface)
{
IMediaEventSink* pEventSink;
IFilterGraph *graph;
HRESULT hr = S_OK;
TRACE("(%p)\n", iface);
graph = iface->filter.filterInfo.pGraph;
if (graph)
{ hr = IFilterGraph_QueryInterface(iface->filter.filterInfo.pGraph, &IID_IMediaEventSink, (LPVOID*)&pEventSink);
if (SUCCEEDED(hr))
{
hr = IMediaEventSink_Notify(pEventSink, EC_COMPLETE, S_OK, (LONG_PTR)iface);
IMediaEventSink_Release(pEventSink);
}
}
RendererPosPassThru_EOS(iface->pPosition);
SetEvent(iface->evComplete);
return hr;
}
HRESULT WINAPI BaseRendererImpl_BeginFlush(BaseRenderer* iface)
{
TRACE("(%p)\n", iface);
BaseRendererImpl_ClearPendingSample(iface);
SetEvent(iface->ThreadSignal);
SetEvent(iface->RenderEvent);
return S_OK;
}
HRESULT WINAPI BaseRendererImpl_EndFlush(BaseRenderer* iface)
{
TRACE("(%p)\n", iface);
QualityControlRender_Start(iface->qcimpl, iface->filter.rtStreamStart);
RendererPosPassThru_ResetMediaTime(iface->pPosition);
ResetEvent(iface->ThreadSignal);
ResetEvent(iface->RenderEvent);
return S_OK;
}
HRESULT WINAPI BaseRendererImpl_ClearPendingSample(BaseRenderer *iface)
{
if (iface->pMediaSample)
{
IMediaSample_Release(iface->pMediaSample);
iface->pMediaSample = NULL;
}
return S_OK;
}

325
reactos/lib/3rdparty/strmbase/seeking.c vendored Normal file
View file

@ -0,0 +1,325 @@
/*
* Filter Seeking and Control Interfaces
*
* Copyright 2003 Robert Shearman
* Copyright 2010 Aric Stewart, CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
/* FIXME: critical sections */
#define COBJMACROS
#include "dshow.h"
#include "wine/strmbase.h"
#include "uuids.h"
#include "wine/debug.h"
#include <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;
}

View file

@ -0,0 +1,50 @@
/*
* Header file for private strmbase implementations
*
* Copyright 2012 Aric Stewart, CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
/* Quality Control */
typedef struct QualityControlImpl {
IQualityControl IQualityControl_iface;
IPin *input;
IBaseFilter *self;
IQualityControl *tonotify;
/* Render stuff */
IReferenceClock *clock;
REFERENCE_TIME last_in_time, last_left, avg_duration, avg_pt, avg_render, start, stop;
REFERENCE_TIME current_jitter, current_rstart, current_rstop, clockstart;
double avg_rate;
LONG64 rendered, dropped;
BOOL qos_handled, is_dropped;
} QualityControlImpl;
HRESULT QualityControlImpl_Create(IPin *input, IBaseFilter *self, QualityControlImpl **ppv);
HRESULT QualityControlImpl_Destroy(QualityControlImpl *This);
HRESULT WINAPI QualityControlImpl_QueryInterface(IQualityControl *iface, REFIID riid, void **ppv);
ULONG WINAPI QualityControlImpl_AddRef(IQualityControl *iface);
ULONG WINAPI QualityControlImpl_Release(IQualityControl *iface);
HRESULT WINAPI QualityControlImpl_Notify(IQualityControl *iface, IBaseFilter *sender, Quality qm);
HRESULT WINAPI QualityControlImpl_SetSink(IQualityControl *iface, IQualityControl *tonotify);
void QualityControlRender_Start(QualityControlImpl *This, REFERENCE_TIME tStart);
void QualityControlRender_SetClock(QualityControlImpl *This, IReferenceClock *clock);
HRESULT QualityControlRender_WaitFor(QualityControlImpl *This, IMediaSample *sample, HANDLE ev);
void QualityControlRender_DoQOS(QualityControlImpl *priv);
void QualityControlRender_BeginRender(QualityControlImpl *This);
void QualityControlRender_EndRender(QualityControlImpl *This);

View file

@ -0,0 +1,641 @@
/*
* Transform Filter (Base for decoders, etc...)
*
* Copyright 2005 Christian Costa
* Copyright 2010 Aric Stewart, CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include <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
};

488
reactos/lib/3rdparty/strmbase/video.c vendored Normal file
View file

@ -0,0 +1,488 @@
/*
* Generic Implementation of strmbase video classes
*
* Copyright 2012 Aric Stewart, CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#include <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);
}

738
reactos/lib/3rdparty/strmbase/window.c vendored Normal file
View file

@ -0,0 +1,738 @@
/*
* Generic Implementation of strmbase window classes
*
* Copyright 2012 Aric Stewart, CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#include "dshow.h"
#include "wine/debug.h"
#include "wine/unicode.h"
#include "wine/strmbase.h"
#include "uuids.h"
#include "vfwmsgs.h"
#include <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;
}

View file

@ -37,7 +37,7 @@ reactos/dll/directx/dsound # Synced to Wine-1.5.26
reactos/dll/directx/dxdiagn # Synced to Wine-0_9_5
reactos/dll/directx/msdmo # Autosync
reactos/dll/directx/qedit # Autosync
reactos/dll/directx/quartz # Autosync
reactos/dll/directx/quartz # Synced to Wine-1.5.26
reactos/dll/win32/activeds # Synced to Wine-1.1.43?
reactos/dll/win32/actxprxy # Synced to Wine-1.5.26
reactos/dll/win32/advpack # Synced to Wine-1.5.26
@ -228,7 +228,8 @@ In addition the following libs, dlls and source files are mostly based on code p
from Winehq CVS. If you are looking to update something in these files
check Wine current souces first as it may already be fixed.
reactos/lib/sdk/uuid # Synced to Wine-1.1.42
reactos/lib/3rdparty/strmbase # Synced to Wine-1.5.26
reactos/lib/sdk/uuid # Synced to Wine-1.1.42
advapi32 -
reactos/dll/win32/advapi32/crypt/*.c # Unknown