mirror of
https://github.com/reactos/reactos.git
synced 2025-06-30 11:31:20 +00:00
[QUARTZ]
* 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:
parent
8eccf8f3b5
commit
1d814c38a6
63 changed files with 15274 additions and 9246 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
};
|
|
@ -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*/
|
|
@ -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"
|
20
reactos/dll/directx/quartz/control_tlb.rgs
Normal file
20
reactos/dll/directx/quartz/control_tlb.rgs
Normal 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
|
@ -26,22 +26,31 @@ WINE_DEFAULT_DEBUG_CHANNEL(quartz);
|
|||
|
||||
typedef struct IEnumFiltersImpl
|
||||
{
|
||||
const IEnumFiltersVtbl * lpVtbl;
|
||||
IEnumFilters IEnumFilters_iface;
|
||||
LONG refCount;
|
||||
IBaseFilter ** ppFilters;
|
||||
int nFilters;
|
||||
IGraphVersion * pVersionSource;
|
||||
LONG Version;
|
||||
IBaseFilter *** pppFilters;
|
||||
ULONG * pNumFilters;
|
||||
ULONG uIndex;
|
||||
} IEnumFiltersImpl;
|
||||
|
||||
static const struct IEnumFiltersVtbl IEnumFiltersImpl_Vtbl;
|
||||
|
||||
HRESULT IEnumFiltersImpl_Construct(IBaseFilter ** ppFilters, ULONG nFilters, IEnumFilters ** ppEnum)
|
||||
static inline IEnumFiltersImpl *impl_from_IEnumFilters(IEnumFilters *iface)
|
||||
{
|
||||
return CONTAINING_RECORD(iface, IEnumFiltersImpl, IEnumFilters_iface);
|
||||
}
|
||||
|
||||
HRESULT IEnumFiltersImpl_Construct(IGraphVersion * pVersionSource, IBaseFilter *** pppFilters, ULONG * pNumFilters, IEnumFilters ** ppEnum)
|
||||
{
|
||||
/* Note: The incoming IBaseFilter interfaces are not AddRef'd here as in Windows,
|
||||
* they should have been previously AddRef'd. */
|
||||
IEnumFiltersImpl * pEnumFilters = CoTaskMemAlloc(sizeof(IEnumFiltersImpl));
|
||||
HRESULT hr;
|
||||
LONG currentVersion;
|
||||
|
||||
TRACE("(%p, %d, %p)\n", ppFilters, nFilters, ppEnum);
|
||||
TRACE("(%p, %p, %p)\n", pppFilters, pNumFilters, ppEnum);
|
||||
|
||||
*ppEnum = NULL;
|
||||
|
||||
|
@ -50,20 +59,19 @@ HRESULT IEnumFiltersImpl_Construct(IBaseFilter ** ppFilters, ULONG nFilters, IEn
|
|||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
pEnumFilters->lpVtbl = &IEnumFiltersImpl_Vtbl;
|
||||
pEnumFilters->IEnumFilters_iface.lpVtbl = &IEnumFiltersImpl_Vtbl;
|
||||
pEnumFilters->refCount = 1;
|
||||
pEnumFilters->uIndex = 0;
|
||||
pEnumFilters->nFilters = nFilters;
|
||||
pEnumFilters->ppFilters = CoTaskMemAlloc(sizeof(IBaseFilter*) * nFilters);
|
||||
if (!pEnumFilters->ppFilters)
|
||||
{
|
||||
CoTaskMemFree(pEnumFilters);
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
pEnumFilters->pNumFilters = pNumFilters;
|
||||
pEnumFilters->pppFilters = pppFilters;
|
||||
IGraphVersion_AddRef(pVersionSource);
|
||||
pEnumFilters->pVersionSource = pVersionSource;
|
||||
|
||||
memcpy(pEnumFilters->ppFilters, ppFilters, nFilters * sizeof(IBaseFilter*));
|
||||
/* Store the current version of the graph */
|
||||
hr = IGraphVersion_QueryVersion(pVersionSource, ¤tVersion);
|
||||
pEnumFilters->Version = (hr==S_OK) ? currentVersion : 0;
|
||||
|
||||
*ppEnum = (IEnumFilters *)(&pEnumFilters->lpVtbl);
|
||||
*ppEnum = &pEnumFilters->IEnumFilters_iface;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -91,7 +99,7 @@ static HRESULT WINAPI IEnumFiltersImpl_QueryInterface(IEnumFilters * iface, REFI
|
|||
|
||||
static ULONG WINAPI IEnumFiltersImpl_AddRef(IEnumFilters * iface)
|
||||
{
|
||||
IEnumFiltersImpl *This = (IEnumFiltersImpl *)iface;
|
||||
IEnumFiltersImpl *This = impl_from_IEnumFilters(iface);
|
||||
ULONG refCount = InterlockedIncrement(&This->refCount);
|
||||
|
||||
TRACE("(%p)->()\n", iface);
|
||||
|
@ -101,15 +109,14 @@ static ULONG WINAPI IEnumFiltersImpl_AddRef(IEnumFilters * iface)
|
|||
|
||||
static ULONG WINAPI IEnumFiltersImpl_Release(IEnumFilters * iface)
|
||||
{
|
||||
IEnumFiltersImpl *This = (IEnumFiltersImpl *)iface;
|
||||
IEnumFiltersImpl *This = impl_from_IEnumFilters(iface);
|
||||
ULONG refCount = InterlockedDecrement(&This->refCount);
|
||||
|
||||
TRACE("(%p)->()\n", iface);
|
||||
|
||||
if (!refCount)
|
||||
{
|
||||
CoTaskMemFree(This->ppFilters);
|
||||
CoTaskMemFree(This);
|
||||
IGraphVersion_Release(This->pVersionSource);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
|
@ -120,18 +127,26 @@ static HRESULT WINAPI IEnumFiltersImpl_Next(IEnumFilters * iface, ULONG cFilters
|
|||
{
|
||||
ULONG cFetched;
|
||||
ULONG i;
|
||||
IEnumFiltersImpl *This = (IEnumFiltersImpl *)iface;
|
||||
LONG currentVersion;
|
||||
IEnumFiltersImpl *This = impl_from_IEnumFilters(iface);
|
||||
HRESULT hr;
|
||||
|
||||
cFetched = min(This->nFilters, This->uIndex + cFilters) - This->uIndex;
|
||||
cFetched = min(*This->pNumFilters, This->uIndex + cFilters) - This->uIndex;
|
||||
|
||||
TRACE("(%p)->(%u, %p, %p)\n", iface, cFilters, ppFilters, pcFetched);
|
||||
|
||||
/* First of all check if the graph has changed */
|
||||
hr = IGraphVersion_QueryVersion(This->pVersionSource, ¤tVersion);
|
||||
if (hr==S_OK && This->Version != currentVersion)
|
||||
return VFW_E_ENUM_OUT_OF_SYNC;
|
||||
|
||||
|
||||
if (!ppFilters)
|
||||
return E_POINTER;
|
||||
|
||||
for (i = 0; i < cFetched; i++)
|
||||
{
|
||||
ppFilters[i] = This->ppFilters[This->uIndex + i];
|
||||
ppFilters[i] = (*This->pppFilters)[This->uIndex + i];
|
||||
IBaseFilter_AddRef(ppFilters[i]);
|
||||
}
|
||||
|
||||
|
@ -147,11 +162,11 @@ static HRESULT WINAPI IEnumFiltersImpl_Next(IEnumFilters * iface, ULONG cFilters
|
|||
|
||||
static HRESULT WINAPI IEnumFiltersImpl_Skip(IEnumFilters * iface, ULONG cFilters)
|
||||
{
|
||||
IEnumFiltersImpl *This = (IEnumFiltersImpl *)iface;
|
||||
IEnumFiltersImpl *This = impl_from_IEnumFilters(iface);
|
||||
|
||||
TRACE("(%p)->(%u)\n", iface, cFilters);
|
||||
|
||||
if (This->uIndex + cFilters < This->nFilters)
|
||||
if (This->uIndex + cFilters < *This->pNumFilters)
|
||||
{
|
||||
This->uIndex += cFilters;
|
||||
return S_OK;
|
||||
|
@ -161,22 +176,27 @@ static HRESULT WINAPI IEnumFiltersImpl_Skip(IEnumFilters * iface, ULONG cFilters
|
|||
|
||||
static HRESULT WINAPI IEnumFiltersImpl_Reset(IEnumFilters * iface)
|
||||
{
|
||||
IEnumFiltersImpl *This = (IEnumFiltersImpl *)iface;
|
||||
IEnumFiltersImpl *This = impl_from_IEnumFilters(iface);
|
||||
HRESULT hr;
|
||||
LONG currentVersion;
|
||||
|
||||
TRACE("(%p)->()\n", iface);
|
||||
|
||||
This->uIndex = 0;
|
||||
hr = IGraphVersion_QueryVersion(This->pVersionSource, ¤tVersion);
|
||||
if (!hr)
|
||||
This->Version = currentVersion;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IEnumFiltersImpl_Clone(IEnumFilters * iface, IEnumFilters ** ppEnum)
|
||||
{
|
||||
HRESULT hr;
|
||||
IEnumFiltersImpl *This = (IEnumFiltersImpl *)iface;
|
||||
IEnumFiltersImpl *This = impl_from_IEnumFilters(iface);
|
||||
|
||||
TRACE("(%p)->(%p)\n", iface, ppEnum);
|
||||
|
||||
hr = IEnumFiltersImpl_Construct(This->ppFilters, This->nFilters, ppEnum);
|
||||
hr = IEnumFiltersImpl_Construct(This->pVersionSource, This->pppFilters, This->pNumFilters, ppEnum);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
return IEnumFilters_Skip(*ppEnum, This->uIndex);
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
50
reactos/dll/directx/quartz/fil_data.idl
Normal file
50
reactos/dll/directx/quartz/fil_data.idl
Normal 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);
|
||||
}
|
|
@ -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;
|
||||
|
||||
TRACE("(%p)\n", pInfo);
|
||||
|
||||
strcpyW(pInfo->achName, This->filterInfo.achName);
|
||||
pInfo->pGraph = This->filterInfo.pGraph;
|
||||
|
||||
if (pInfo->pGraph)
|
||||
IFilterGraph_AddRef(pInfo->pGraph);
|
||||
if (strcmpW(Id, wszOutputPinName))
|
||||
{
|
||||
*ppPin = NULL;
|
||||
return VFW_E_NOT_FOUND;
|
||||
}
|
||||
|
||||
*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
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -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,8 +356,8 @@ 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);
|
||||
|
@ -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);
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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; }
|
||||
|
|
269
reactos/dll/directx/quartz/quartz_strmif.rgs
Normal file
269
reactos/dll/directx/quartz/quartz_strmif.rgs
Normal 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' }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 }
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
};
|
|
@ -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);
|
|
@ -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
2304
reactos/dll/directx/quartz/vmr9.c
Normal file
2304
reactos/dll/directx/quartz/vmr9.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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));
|
||||
|
|
|
@ -19,7 +19,6 @@ list(APPEND SOURCE
|
|||
mmstream.idl
|
||||
qedit.idl
|
||||
regbag.idl
|
||||
strmif.idl
|
||||
tvratings.idl
|
||||
vidcap.idl
|
||||
videoacc.idl
|
||||
|
|
|
@ -45,6 +45,7 @@ interface IAMVfwCompressDialogs;
|
|||
interface IAMVideoCompression;
|
||||
interface IAMVideoDecimationProperties;
|
||||
interface IAMVideoProcAmp;
|
||||
interface IAMGraphBuilderCallback;
|
||||
interface ICaptureGraphBuilder;
|
||||
interface ICaptureGraphBuilder2;
|
||||
interface IConfigAviMux;
|
||||
|
@ -235,14 +236,14 @@ typedef struct
|
|||
{
|
||||
ULONG cPins;
|
||||
[size_is(cPins)] const REGFILTERPINS *rgPins;
|
||||
} DUMMYSTRUCTNAME;
|
||||
} DUMMYSTRUCTNAME1;
|
||||
|
||||
[case(2)]
|
||||
struct
|
||||
{
|
||||
ULONG cPins2;
|
||||
[size_is(cPins2)] const REGFILTERPINS2 *rgPins2;
|
||||
} DUMMYSTRUCTNAME1;
|
||||
} DUMMYSTRUCTNAME2;
|
||||
|
||||
[default]
|
||||
;
|
||||
|
@ -1070,6 +1071,21 @@ interface IAMFilterMiscFlags : IUnknown
|
|||
ULONG GetMiscFlags();
|
||||
};
|
||||
|
||||
[
|
||||
local,
|
||||
object,
|
||||
uuid(4995f511-9ddb-4f12-bd3b-f04611807b79),
|
||||
pointer_default(unique)
|
||||
]
|
||||
interface IAMGraphBuilderCallback : IUnknown
|
||||
{
|
||||
HRESULT SelectedFilter(
|
||||
[in] IMoniker *pMon);
|
||||
|
||||
HRESULT CreatedFilter(
|
||||
[in] IBaseFilter *pFil);
|
||||
};
|
||||
|
||||
[
|
||||
local,
|
||||
object,
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
660
reactos/include/reactos/wine/strmbase.h
Normal file
660
reactos/include/reactos/wine/strmbase.h
Normal 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);
|
1
reactos/lib/3rdparty/CMakeLists.txt
vendored
1
reactos/lib/3rdparty/CMakeLists.txt
vendored
|
@ -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)
|
||||
|
|
23
reactos/lib/3rdparty/strmbase/CMakeLists.txt
vendored
Normal file
23
reactos/lib/3rdparty/strmbase/CMakeLists.txt
vendored
Normal 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
84
reactos/lib/3rdparty/strmbase/audio.c
vendored
Normal 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;
|
||||
}
|
79
reactos/lib/3rdparty/strmbase/dispatch.c
vendored
Normal file
79
reactos/lib/3rdparty/strmbase/dispatch.c
vendored
Normal 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
469
reactos/lib/3rdparty/strmbase/dllfunc.c
vendored
Normal 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;
|
||||
}
|
|
@ -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
228
reactos/lib/3rdparty/strmbase/filter.c
vendored
Normal 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;
|
||||
}
|
307
reactos/lib/3rdparty/strmbase/mediatype.c
vendored
Normal file
307
reactos/lib/3rdparty/strmbase/mediatype.c
vendored
Normal 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
|
||||
};
|
310
reactos/lib/3rdparty/strmbase/outputqueue.c
vendored
Normal file
310
reactos/lib/3rdparty/strmbase/outputqueue.c
vendored
Normal 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
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
938
reactos/lib/3rdparty/strmbase/pospass.c
vendored
Normal 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
|
||||
};
|
318
reactos/lib/3rdparty/strmbase/qualitycontrol.c
vendored
Normal file
318
reactos/lib/3rdparty/strmbase/qualitycontrol.c
vendored
Normal 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
614
reactos/lib/3rdparty/strmbase/renderer.c
vendored
Normal 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
325
reactos/lib/3rdparty/strmbase/seeking.c
vendored
Normal 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;
|
||||
}
|
50
reactos/lib/3rdparty/strmbase/strmbase_private.h
vendored
Normal file
50
reactos/lib/3rdparty/strmbase/strmbase_private.h
vendored
Normal 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);
|
641
reactos/lib/3rdparty/strmbase/transform.c
vendored
Normal file
641
reactos/lib/3rdparty/strmbase/transform.c
vendored
Normal 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
488
reactos/lib/3rdparty/strmbase/video.c
vendored
Normal 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
738
reactos/lib/3rdparty/strmbase/window.c
vendored
Normal 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;
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue